Front-End Fundamentals: A practical guide to front-end web development

103

Transcript of Front-End Fundamentals: A practical guide to front-end web development

Page 1: Front-End Fundamentals: A practical guide to front-end web development
Page 2: Front-End Fundamentals: A practical guide to front-end web development

Front-EndFundamentals

Apracticalguidetofront-endwebdevelopment.

JoeFenderandCarwinYoung

Thisbookisforsaleathttp://leanpub.com/front-end-fundamentals

Thisversionwaspublishedon2015-02-11

*****

ThisisaLeanpubbook.LeanpubempowersauthorsandpublisherswiththeLeanPublishingprocess.LeanPublishingistheactofpublishinganin-progressebookusinglightweighttoolsandmanyiterationstogetreaderfeedback,pivotuntilyouhavetherightbookandbuildtractiononceyoudo.

*****

©2014-2015JoeFenderandCarwinYoung

Page 3: Front-End Fundamentals: A practical guide to front-end web development

Thanksto,

SallyRose,CarrieYoungandJustinHarrell

Page 4: Front-End Fundamentals: A practical guide to front-end web development

TableofContents

AbouttheAuthorsJoeFenderCarwinYoung

IntroductionWhoThisBookIsForAnOverviewofThisBookExampleCodeContactingtheAuthors

GettingStartedExpectationsofaFront-EndDeveloperSettingUpYourLocalEnvironment

FrameworksModel-View-WhateverArchitectureSingle-PageApplicationsAngularJSBackbone.jsEmberSummary

StylingResponsiveWebDesignAuthoringMethodologiesPreprocessorsPerformanceandCSSStylingSummary

DependencyManagementWhatisaPackageManager?Node.jsandtheNodePackageManager(npm)BowerBundlerDocumentationSummary

AutomationTaskRunnersGrunt

Page 5: Front-End Fundamentals: A practical guide to front-end web development

GulpCodeKitYeomanOtherTipsSummary

Summary

AppendixAccessibilityAutomationDeploymentLearningResourcesFrameworksLanguagesOnlineServicesPackageManagersPerformanceSoftwareStylingTemplatingTestingVersionControlWebServers

Page 6: Front-End Fundamentals: A practical guide to front-end web development

AbouttheAuthors

JoeandCarwinstartedworkingtogetherin2013atLullabot,aninteractivestrategy,designanddevelopmentcompany.

AtLullabot,theyworkwithdecisionmakers,developers,anddesignersatallstagesofawebproject.TheyhaveguidedthedevelopmentofsitesforclientssuchasMarthaStewart,TheGRAMMYs,MTVUK,SonyMusic,LifetimeTelevision,TheGeorgeLucasEducationalFoundation,LeoLaporte’sTWiTnetwork,andmanyothers.

JoeFender

JoeFenderlivesinLondon,UKandsplitshisfocusbetweenfront-endandback-enddevelopment.SpecializinginPHP,AngularJSandDrupal,JoewastheleadarchitectatStudioUmi,thelargestDrupalshopinJapanbeforejoiningLullabottoworkonawesomewebsitessuchasDrupalize.MeandMSNBC.

Inhissparetime,Joelikestocollectshoesandworkonsideprojects.Butneveratthesametime.

CarwinYoung

CarwinYoungisanexpertfront-enddeveloperlivinginSpringfield,Missouri.Hehasover8yearsexperienceworkingonthefront-end.Hewasthesecondfront-enddevelopertoworkatLullabotwherehehasplayedakeyroleonbuildingwebsitesforclientssuchasMSNBC,BravoTVandtheGRAMMYs.

Carwinlovestosharehisexpertise.HehasspokenontopicssuchasRapidDrupalDevelopmentatDrupalCampChicago,isaco-organizerfortheSpringfieldDrupalmeet-

Page 7: Front-End Fundamentals: A practical guide to front-end web development

upandisaregularcontributortotheFront-endRapport,anonlinemagazineforfront-enddevelopers.

Page 8: Front-End Fundamentals: A practical guide to front-end web development

Introduction

Front-endwebdevelopmentisevolving.LonggonearethedaysofwritingstaticHTMLfileswithself-containedCSS.Aswebdevelopersinthismodernworld,weneedtounderstandandutilizeanendlessnumberofframeworks,plugins,techniquesandmore.Knowingtherighttoolstouseandwhentousethemiskeytobuildingsuccessfulsolutions.

Despiteourbestefforts,itcanbedifficulttokeepupwiththespeedofadvancingwebdevelopment.Wesureashellcan’tslowitdown.Andwhywouldwewantto?It’ssoexcitingtonotknowwheretechnologyisheadedandwhatcouldbearoundthenextcorner.Weshouldbothprepareforchangeandembraceit.Andthatisexactlywherefront-enddevelopersexcel.Webuildwhattheconsumerseesandbecauseofthat,wewanttousethemostcutting-edgetechnologiestocreatethebiggestimpact.

Thisbookcametobefromthelessonswe,theauthors,havelearntthroughtrialanderrorwhilstworkingonfront-enddevelopmentprojectsrangingfromenormoushigh-trafficsitessuchasMSNBC,TheGRAMMYsandBravoTVtostartupsandexperimentssuchasDrupalize.MeandBracketCloud.Wewanttosharewithyouthetoolsthatweuseandthestandardsthatwefollow.Ourultimategoalisforyoutowalkawayunderstandingthecoreconceptsoffront-enddevelopmentsoyoucanconfidentlygoandworkonyourownprojects.

Thisbookissomewhatopinionatedbasedonourexperience,soyou’llfindsomeofthecontentheavilygearedtowardsaparticularwayofdoingthings.Ofcourse,therearemanywaysofaccomplishingthesametaskintheworldoffront-enddevelopment;that’swhatmakesitsoaccessibleandyetsocomplicated.Learningonewayofdoingsomethingcanmakelearningthealternativesamuchmorepalatabletask,soweencourageyoutolookintoanyandallofthetechnologiespresentedhereinandevengoontoseeifsomethingelsemightbetterfityourneeds.

WhoThisBookIsForThecontentinthisbookisaimedatthosewhoarenewtofront-endwebdevelopment.Regardlessofwhetheryouareabeginnerorexpertdeveloper,theconceptsoutlinedinthisbookareessentialtoembracingtherapidlyevolvingweb.Wewon’tbecoveringthegeneralbasicsofwebdevelopmentsoyouwillmostlikelywanttogetuptospeedonthefundamentalsofwebprogrammingsuchasHTML,CSSandJavaScript.Wewillalsobeutilizingthecommandline,sosomebasicknowledgeofhowtousethatonyouroperatingsystemisrecommended.

Ifyouhearyourselfaskinganyofthefollowingquestions,thisbookwilllikelybeveryusefulforyou!

Page 9: Front-End Fundamentals: A practical guide to front-end web development

“Whatactuallyisfront-enddevelopment?”“HowcanIbeamoreefficientwebdeveloper?”“WhatisGrunt/AngularJS/SASS/<insertpopulartoolnamehere>?”“HowdoIfitallofthesefront-endtoolstogetherintoaproject?”“HowcanIbuildafront-endapplicationthatcanscale?”

AnOverviewofThisBookEverywebprojectthatyouworkonisdifferentandthereisno‘onesizefitsall’setoftools.However,throughoutthechaptersinthisbook,we’llintroduceyoutosomeofthemostpopular,usefulandpowerfultoolsusedinfront-endwebdevelopmentsothatwhenyou’redonereadingyouwillbeabletoapplytheconceptsandtechniquestowhateveryouareworkingon.

1.GettingStartedTheaimofthefirstchapterofthisbookistohelpgetyouacclimatedwithfront-enddevelopmentingeneral.You’lllearnwhat’sexpectedfromafront-enddeveloperandgetashortoverviewofthetypesofprojectsafront-enddevelopermightbetaskedwith.We’lleventakeyouthroughsettingupyourcomputerforlocaldevelopment.

2.FrameworksThischapterjumpsrightintosomeofthemorepopularJavaScriptframeworksandtemplatelanguagesinusetoday.We’llcoverthedetailsofwhatexactlya‘framework’isandtalkabouttheMVCpatternbeforegettingintothedetailsofinstallationandpracticalusageof3popularframeworks:AngularJS,Backbone.jsandEmber.js.

3.StylingThere’salotmoretostylingthanjustthrowingCSSatyourmarkup;thatjustleadstoabigmessofunreadablespaghetticodesprinkledwith!importantparmesan.Herewe’llcoverCSSpreprocessorslikeSass,organizationalmethodsforyourstyles,andthekindofimpactyourCSSmayhaveonaproject’sperformance.

4.DependencyManagementGettingyourwholeteamonthesamepagecode-wisecanbechallenging.Heck,evenmakingsureyou’reusingthesameversionofthatawesomeRubygemafteranupdatecanbeapain.Thischapterondependencymanagementcoversanumberofreallyhandyfront-endpackagemanagerslikenpm,Bower,andBundler.You’lllearnwhatapackagemanagerisandhowtouseiteffectivelytokeepyourprojectontrack.

5.AutomationDoyoulikedoingthesamerepetitivetasksoverandover?No?Neitherdowe.

Theautomationchapterisaboutjustthat,automation.We’llgooverhowyoucanremovethetediumfromfront-enddevelopmentandjustgettowork.Inthischapteryou’lllearnhowtoperformtaskslikecheckingyourJavaScriptorCSSforerrorswheneveryousavea

Page 10: Front-End Fundamentals: A practical guide to front-end web development

file,minifyyourcodetoshaveoffsomefilesize,andevenhowtoautomaticallyrefreshyourbrowserwheneversomethingchanges.Onceyougetstarted,you’llneverlookback.

ExampleCodeThisbookcontainsmanycodesnippetsfordemonstrationpurposes.Codemayappeardifferentlydependingonthedeviceyouareusingtoreadthisbook.Hereisanexampleofacodesnippetsoyouknowwhattoexpect:1vargulp=require('gulp'),

2uglify=require('gulp-uglify');

3

4//ThistaskuglifiesourJSfiles.

5gulp.task('compress',function(){

6gulp.src('src/js/*.js')

7.pipe(uglify())

8.pipe(gulp.dest('dist'))

9});

Youwillalsonoticethatwereferencecodeinlinelikethisthroughoutthebook.

ContactingtheAuthorsIfyouhaveanyfeedbackorquestions,pleasefeelfreetocontactusviatheFront-EndFundamentalsGoogleGroup.

Youcaneithercreateanewtopicviathewebinterfaceoryoucansendanemailtothemailinglistaddress:[email protected]

Wewilldoourbesttoconsidereachandeverynewmessagereceived.Pleaseunderstandthatdependingonthevolumeofrequests,itmaybedifficultforustorespondimmediately.

Page 11: Front-End Fundamentals: A practical guide to front-end web development

GettingStarted

Traditionally,whenwebdevelopersstartedbuildingwebsitesinthe90s,theywouldwearallthehats.Theywouldsetuptheserver,writealltheserver-sidecode(inPHP)thatwouldeventuallyoutputHTMLandfinallysprinkleonsomeCSStomakethingslookpretty.Ifyouhaveabackgroundinwebdevelopment,thismaysoundveryfamiliartoyou.

Duetotheadvancementofmodernwebtechnologiesandcomputerhardware,we’reabletocreatemoresophisticatedexperiencesthanever.Becauseofthiscomplexity,theroleofawebdeveloperhasnaturallyevolvedandsplitintoseparatedisciplines.Specifically,alinewasdrawnbetweentheback-endandfront-end.Back-endbeingserver-sideprogrammingandfront-endbeingclient-side.Front-endshouldnotbeconfusedwithwebdesign.Althoughfront-enddeveloperscanbenefitfrompossessingdesignerchops,theirroleisn’ttodesignawebsitebutrathertoimplementadesigngiventothem.Dependingonthesizeofteamyouworkwith,youmayfindthelinesbetweentheserolesblurred.Youshoulddefinitelyreadthisgreatarticleontheconfusionwhichrevolvesaroundthedefinitionofafront-enddeveloper.

Thedividebetweenback-endandfront-endisstillnew.We’renotyetcompletelycomfortablewithit.Someback-enddevelopersstilldoalotoffront-endwork,orvice-versa.Sometimesitcanbetrickytofigureouthowtocommunicatefromeithersideofthedivide.However,whenyoulookatjobpostingsforwebdevelopersthesedaysyou’lloftenseethemlistedaseitherforaback-endorfront-endcandidate.Theindustryasawholehasembracedtheconceptofroleseparationforwebdeveloperswhichcanonlyleadtogoodthingsaswecannowspecializeinourdisciplineofchoice.

Beingafront-enddeveloperissoexciting.You’reonthe‘forefront’sotospeakandhaveadirectimpactonhowtheuserfeelsaboutandinteractswiththeproductorservicethatthewebsitesyoubuildportray.Youcaninstantlyseetheresultsofyourworkandbecauseofthisyouwillreceivealotoffeedback,sometimesharsh.Buttakeitwithagrainofsaltanduseitconstructivelytoimproveonyourselfandtheworkthatyoudo.

ExpectationsofaFront-EndDeveloperWhatyou’regoingtorealizebythetimeyou’vefinishedthisbookisthatthefront-endworldisbig.Therearesomanypeopleworkingtowardsthesamegoalbutwithdifferentpointsofviewonhowtogetthere.Thatisthebeautyofopen-source.You’regoingtofeelalittleoverwhelmedbutdon’tletthatfazeyou.Learntolovetryingnewthingsandembracechangeasitcomesandyou’regoingtodoreallywell.Hereisasummaryofthevariousthingsyoushouldconsiderwhentryingtobethebestfront-enddeveloperyoucan:

Page 12: Front-End Fundamentals: A practical guide to front-end web development

Ratherthansettingouttomasterasingletool,trytolearnalittleabouteachofthemandhowtheyworktogetherfirst.Whenyou’vegraspedthebiggerpicture,itismucheasiertospecialize.Ifyou’rereadingthisbook,you’redefinitelyontherighttrack.Lovetolearn.Tokeepupwiththespeedofevolvingwebtechnologies,you’llhavetopickupnewthingsregularlyoryoumayfallbehind.Beagoodcommunicator.Evenifyou’reworkingalone,you’llfindthattherearemanyopportunitiesonlinetointeractwithotherdevelopersandgetsupport.Googleisyourfriend.Whenanyoneasksme“Howdoyougoaboutsolvingaproblem?”myansweralwaysstartswithGoogleandthatisperfectlyOK!Googleisthekeeperofmuchknowledgeandyoushouldlearntouseitinabundance.Don’treinventthewheel.You’regoingtofindsomeoneelsehasprobablythoughtofasimilarsolutiontotheproblemyou’refacing.Itmaynotbetheperfectmatchbutbybendingyourprojecttomakeroomforpre-existingsolutions,you’realsobenefitingfromthecommunityandsupportthatcomeswiththem.Cross-everything.You’reresponsibleformakingsurewhatyoubuildactuallyworksandisn’tdependentontheuserhavingaspecificbrowserordevice.Buildcross-browser,cross-platformandcross-device.Askoutsidetheboxquestionslike“WhatifIamaccessingthiswebsitefromamobileonaslow3Gconnection?”or“WhatifIamviewingonaniPhone4inlandscape?”.Testandthentestagain.Testforvisualregressions(e.g.usingWraithorPhantomCSS),rununitandfunctionaltestsonyourJavaScript(KarmaorJasminearegoodplacestostart)andtestforgeneralperformance(readtheYahoobestpracticesandtryYSlow).Awelltestedsitemakesallthedifferencesomakesuretocreatetimefortesting.Thinkaboutaccessibility.Forexample,askyourselfhowwillablindpersonorsomeonewhoiscolorblindinteractwithyourwebsite?Hereisausefulchecklistofthingstothinkabout.Documenteverything.Notonlydoesithelpeducatenewdevelopersaboutthetheorybehindyourcodebuttheactofwritingcommentswillhelpyoutospotflawsinyourlogic.Savetimewithautomation.Therearealotofrepetitivetasksinfront-enddevelopmentthatcanbeautomatedtosavetime.Wefinditsoimportantthatwe’veevenwrittenanentirechapteronautomationinthisbook!Learnaboutcollaborationtools.Asawebdeveloper,youaregoingtouseGithubatsomepoint.SoyouwouldbebetterofflookingintoGitanditsvariouspopularworkflowssuchasgit-floworGithubflow.ReadaboutContinuousIntegration.Althoughyoumaynotbeabletoincorporateitintoeveryproject,learningaboutitsprincipleswillhelpyouapproachcodedeploymentinamoreintelligentway.Haveagoodeyefordesign.Asomewhatoverlookedassetoffront-enddevelopersisbeingabletoprovidefeedbacktodesigners.Seeingaswe’retheoneswhoactuallybuildtheinteractions,wewillprobablyusethewebsitealotmorethanthedesignerseverwill.Theywillgreatlyappreciateanyfeedbackyoucangivesodon’tbehesitanttopointoutflawsintheUI.Learnaboutserver-sidewebdevelopmentconcepts.Althoughyoumaynotbetouchingtheback-end,itcanhelpifyouknowwhatisgoingonandhowthedatayou

Page 13: Front-End Fundamentals: A practical guide to front-end web development

areusingactuallygottoyou.

SettingUpYourLocalEnvironmentAlotoffront-enddevelopmenthappensoneitheralocalmachineoranon-productionwebserversetupformultiplepeopletouse.Longgone(hopefully)arethedaysofjusteditingCSSonalivesitebyoverwritingCSSfilesoverFTP.Asdevelopers,weprefertodoeverythinglocallysowedon’tneedtoworryifwe’regoingtoaccidentallyruinourproductionsite.Alsoit’sjustplainfastersincethere’snoneedtoconnecttotheinternet.

Settingupyourlocalenvironmentcouldprobablybeabookinitself(thereareatonofviableoptions),butwe’regoingtocoverwhatwethinkisprobablytheeasiestmethod:MAMP.

MAMPMAMPisaneasytouse,freeapplicationforMacandWindowsbasedmachines.MAMPwillinstallPHP,MySQL,andtheApachewebserverinasimpletomanageenvironmentandyoucanstartupyourwebserverwithaclickofabutton.

Installation

Let’swalkthroughafirstrun:

1. ThefirststepintheinstallationprocessistogodownloadtheMAMPinstallerforyouroperatingsystem.

2. Oncethedownloadcompletes,runtheinstallerprogramthatyoudownloaded.3. Walkthroughtheinstallationprocess.Onceitfinishes,you’llbereadytostartusing

MAMP*.

Page 14: Front-End Fundamentals: A practical guide to front-end web development

*:TheMAMPinstalleralsoinstallsMAMPPROwhichhassomeextrafeaturesifyouchoosetopayforthem.

Setup

Onceyou’vemadeitthroughtheinstaller,runtheMAMPapplication.

WhenMAMPisopen,you’llseea“StartServers”buttonontherightsideofthescreen.Youcanclickitnowandyou’llbeinbusinesswithyourdocumentrootset,whichistheplaceallyoursitefileswillgo,tothedefaultpath.InthecaseofOSX,thedefaultdocumentrootisinthehtdocsdirectorywhereveryouinstalledMAMP(typicallyin/Applications/MAMP).

Ifyouwanttochangeyourdocumentroottoanotherlocation,changetheversionofPHPthattheserveruses,oranumberofothersettings,makesuretostoptheserversandheadtothePreferencespaneofMAMP.

ThedefaultconfigurationofMAMPisfineforgettingstarted,soifyoudon’tneedtocustomizeanythingjuststarttheserversandyoushouldbeabletoaccessatestpageat

Page 15: Front-End Fundamentals: A practical guide to front-end web development

http://localhost:8888/MAMP/.Thispageisn’tontheinternetanywhere,it’sonyourlocalmachine!Ifthatlinkworksforyou,you’rereadytostartdeveloping.Justcreateasimplehtmlpageinsideyourdocumentrootfolder,andyoushouldbeabletoaccessitathttp://localhost:8888/your_file.html.

Foramoredetailedinstallationandset-upguide,takealookattheMAMPuserguide.

SummaryMAMPisagreattoolandonethat’seasytosetupandgetstartedwith.Thereisabigwideworldofwebserversolutionsfordevelopinglocally;heck,ifyou’reonaMacyouhaveApache/PHP/MySQLalready!Therejustisn’tagreatinterfaceforputtingthosethingstouse,somanydeveloperspreferMAMP.Intheend,howeveryougoaboutservingyourHTML/CSS/JStoabrowserisfine.What’simportantisthatitworksforyou.

Page 16: Front-End Fundamentals: A practical guide to front-end web development

Frameworks

JavaScriptallowsyoutowriteclient-sidescriptsformanipulatingtheDOMandforinteractingwiththeuserandtheirbrowser.JavaScriptiscommonlywrittenprocedurallyusinglibrariessuchasjQuery.AsHTML,browsersandJavaScripthavebecomemorepowerful,sohasthecomplexityofJavaScriptfiles.Butthisgrowthcanquicklyleadtospaghetticodeandawholebunchofmaintenancenightmaresasitisquitecommoninwebdevelopmentforasite’sentireJavaScripttobemaintainedinasinglefile.Overtheyears,developershaveattemptedtotackletheissueofgrowingdemandforJavaScriptbycreating‘frameworks’toapproachimplementationinamoremodularway.Frameworkshelptoorganizecode.

TherearealargenumberofJavaScriptframeworksavailable.Inthischapteryou’llbeintroducedtosomeofthemostpopularones.

Themajorityofframeworksincorporateavariationofthe‘Model-View-Controller’(MVC)architecturalpattern.It’sworthnotingthatyoumaycomeacrossafewinathewildthatintroducetheirowntakeonMVC,ortheymayhaveanentirelydifferentstructure.IfyouhaveabackgroundinsoftwareengineeringyoumayalreadybefamiliarwithMVC,butlet’sgooveritbrieflysowe’reallonthesamepage.

Model-View-WhateverArchitectureMVCisapopulararchitecturalpatternthatisusedinmanyJavaScriptframeworks.Aspreviouslymentioned,therearesomeframeworksouttherethatputtheirownspinontheMVCpattern.TheseframeworksimplementwhatissometimesreferredtoasanMV*orMVW(Model-View-Whatever)architecture.

However,itisimportanttoknowwhatMVCis,andwhyithasbeensuchanimportantpartofthewayapplicationsarebuilt.MVCseparatesthedifferentaspectsofanapplicationintothreecomponents:

Model

Modelsrepresentanapplication’sdata.Youcanthinkofeachmodelasadifferentcategoryofdatathatanapplicationwillstore.Forexample,atypicalwebapplicationmayhaveUserandArticlemodels.Modelsdonotoutputanything,asthisisthejobof‘views’,buttheyarecommonlyresponsiblefortellingviewswhentheirdatahasbeenupdated.

View

Viewshandleoutput.Inmostimplementationstheywilloutputthemarkupthatrepresentstheuser-interface.Viewsrequestinformationfrommodelsinordertogeneratethisoutput,andmodelskeepthemuptodate.

Page 17: Front-End Fundamentals: A practical guide to front-end web development

Controller

Controllersareresponsibleforhandlinguserinputsuchasformdatasubmissionorclickevents.Theycansendrequeststomodelsinordertomanipulatetheirdata.

ThefollowingdiagrammayhelpyouvisualizethevariouscomponentsofanMVCfromtheuser’sperspective:

IfyoufancyreadingmoreaboutJavaScriptarchitecturalpatterns,AddyOsmani’sbookLearningJavaScriptDesignPatternsishighlyrecommended.

Single-PageApplicationsWhenlearningaboutJavaScriptframeworks,onetermyoumightseefloatingaroundis‘single-pageapplication’,or‘SPA’.

WhenbuildinganSPA,theUIandapplicationlogicisessentiallyshiftedfromtheservertotheclient.AlltheresourcesforanapplicationsuchasHTML,CSSandJavaScriptaredownloadedinasinglepageload.Astheusernavigatesasite,thebrowserwillnotreloadthepagebutinsteadtheSPAisresponsibleforrenderingthedifferentpartsofapageattherighttime.

CreatinganSPAprovidesamorefluiduserexperiencethanthemoretraditionalapproachofrequestinganewpageeverytimetheusernavigatessomewhere.Bymovingalltheapplicationlogictothefront-end,therequirementsoftheserveraredrasticallyreduced.Insteadoftheserverrenderingeachpageeverytimethereisapagereload,anSPAdynamicallyrequestsonlytherequiredrawdatabehindthescenes,andusesthattorenderthevariousviews.

JavaScriptframeworkscanmakeitfairlyeasytobuildanSPA.Infact,someofthembuildtheirfunctionalityentirelyaroundtheconcept.However,thereareafewdisadvantages

Page 18: Front-End Fundamentals: A practical guide to front-end web development

thatyoumaywanttoconsiderbeforetakingtheplunge.

Forexample,SPAsneedJavaScript.IftheuserdisablesJavaScriptintheirbrowser,thesitewon’trender.It’sdifficulttosayhowmanyusersactuallydothisbutaccordingtocertainstudiesit’slessthan1%.Soyouhavetoaskyourselfifitisactuallyworthsupportingthoseusersandifnot,whatexperiencecanyouprovidefortheminstead?

You’llalsoneedtoconsiderrobots.Maybenotthekindofrobotsyou’rethinkingofbuttheonesthatGoogle,FacebookandTwittercansendtofindoutaboutapage.Theserobotsscrapeapageformetatagsandotherinformationaboutcontentsotheycandisplaythemappropriatelyinsearchenginesorsocialnetworks.Morerecently,GooglerobotshavestartedtorenderJavaScript.ThismeansthatwhenaGooglerobothitsanSPA,itshouldcorrectlyrenderthepagefirstusingJavaScript.However,otherrobots(suchasFacebook’s)areyettoimplementthisfunctionality,andthiscancausesharedpagesfromasitetoproduceundesirableresults.You’llneedtocomeupwithawaytorenderdataserver-sidefortheserobots.Servicesexisttosolvethisexactproblem,suchasPrerender.io.

BeforeyoustarttouseJavaScriptframeworkstobuildSPAs,thinkcarefullyabouttherequirementsofyourapplication.Itcanbequiteeasytoover-complicatethings.Forexample,ifyou’rebuildinganapplicationwherethereisaheavyemphasisonuserinteraction,suchasaticketmanagementsystemorato-dolist,thenyou’lldefinitelybenefitfromusingaJavaScriptframeworkandSPA.However,ifyou’recreatingapagewhichonlyrequiresverybasicinteraction,suchasaportfoliopagegivingdetailsaboutyouandyourwork,thenitcouldbeoverkill.Youmayfindthatthetraditionalapproachtowebdevelopment(i.e.renderingontheserver-sideusingalanguagesuchasPHPandthenaddingontheclient-sideinteractionsusingjQuery)wouldmakelifealoteasier.

AngularJS

AngularJSisanopen-sourcewebapplicationframeworkthatismaintainedbyGoogle.ItisagreatfitfordynamicwebapplicationsandSPAs.

OverviewThewaythatAngularJS(morecommonlyreferredtoasAngular)approacheswebapplicationdevelopmentisunique.ItpromotesHTMLsyntaxextensiontoincludeadditionaltagattributestoelements.Theseattributes,knownas‘directives’,allowyoutoattachnewbehaviortoDOMelements.Angularcomespackagedwithseveraldirectivesforcommonactivitiessuchasdatabinding,repeatingorhidingDOMelements,eventhandlingandformmanagement.Youcanalsowriteyourowndirectives,butthatwillbecoveredlater.

Page 19: Front-End Fundamentals: A practical guide to front-end web development

InstallationAswithmostJavaScriptframeworks,toinstallAngularallyouneedtodoisincludethelibraryonyourpage.Let’sworkthroughanexampletogethertoillustratethis.Inourexample,we’lllaythefoundationsforanapplicationthatwillallowuserstoviewthetimezonesfordifferentcitiesaroundtheworld.Let’scallitTimezoneFinder.YoucanfindthesourcecodeforTimezoneFinderinthisrepository:https://github.com/fender/TimezoneFinder.

Createanewfolderfortheprojectandcreateanindex.htmlfileatitsroot:1<!doctypehtml>

2<html>

3<head>

4<metacharset="utf-8">

5<title>TimezoneFinder</title>

6</head>

7<body>

8<p>Helloworld!WelcometoTimezoneFinder.</p>

9</body>

10</html>

HeadovertotheofficialAngularJShomepageandclickthedownloadbutton.GooglehostsAngularonitsCDNsoyou’reabletoleveragethatquiteeasilywithasimplecopy-and-pasteofthegivenCDNURL.Alternatively,youcandownloadthefiledirectlyor,ifyouprefertohostitlocally,youcanuseBower(seetheDependencyManagementchapter).

Let’sreturntoourexampleandaddtheCDNreferencetoourindex.html:1<head>

2<metacharset="utf-8">

3<title>TimezoneFinder</title>

4<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.mi\

5n.js"></script>

6</head>

Next,wecancreateaapp.jsfilethatwillberesponsibleforkick-startingtheAngularapplication.Butfirst,let’sjustaddasinglelinetooutputtheincludedversionofAngulartothebrowserconsolesothatwecanconfirmithasbeenloadedsuccessfully:1console.log(angular.version.full);

Weneedtomakesureweincludeapp.jsinourpageafterAngularhasbeenincluded:1<head>

2<metacharset="utf-8">

3<title>TimezoneFinder</title>

4<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.mi\

5n.js"></script>

6<scriptsrc="./app.js"></script>

7</head>

VisitthesiteonalocalwebserverandyoushouldseetheAngularversionnumberoutputtoyourbrowserconsole.

Modules

Page 20: Front-End Fundamentals: A practical guide to front-end web development

AnycustomfunctionalitythatyouwishtoimplementwithAngularmustbedefinedinamodule.WhenAngularstartsitlooksforadefaultmoduletoauto-bootstraptheapplication.YoucantellAngularwhichmoduletousebyusingthengAppdirective.

Inourexample,let’saddthedirectivetoour<body>tag:1<bodyng-app="timezoneFinderApp">

AngularreferstodirectivesinlowerCamelCase(e.g.ngApp)butwhenyouwritetheminyourmarkupyouneedtowritetheminlowercaseandseparatewordswithhyphens.Inourexample,we’venamedourmoduletimezoneFinderAppsolet’sgoaheadandcreatethismoduleinourapp.jsscriptfile:1varapp=angular.module('timezoneFinderApp',[]);

That’sallittakestoinitializeanewmodule.However,nothingwillactuallyhappenjustyet.Let’smoveontocontrollerstoreallygetthispartystarted!

ControllersAngularcontrollersallowyoutowritefunctionalitythatinteractswithascopeobject.Itcantakealittletimetogetyourheadaroundscopesandhowtheyworkbutit’simportanttorememberthattheyarethegluebetweencontrollersandviews.Bothcontrollersanddirectiveshaveaccesstothescopeobjectbutnotwitheachotherdirectly.

ThebestwaytounderstandthisistoreturntoourTimezoneFinderexample.Let’swriteourfirstcontrollerdirectlyinapp.js:1varapp=angular.module('timezoneFinderApp',[]);

2

3app.controller('MainController',['$scope',function($scope){

4//Definesourcities.

5$scope.cities=[

6{name:'London',timezone:'GMT'},

7{name:'Tokyo',timezone:'JST'},

8{name:'Melbourne',timezone:'EDT'},

9{name:'LosAngeles',timezone:'PST'},

10{name:'NewYork',timezone:'EST'}

11];

12

13//Thedefaultcity.

14$scope.selectedCity=$scope.cities[0];

15}]);

We’venamedourcontrollerMainControllersince,forthisexample,we’reonlygoingtoneedasinglecontroller.However,forlargerapplicationsyou’lloftenendupwantingtonametheminrelationtothefunctionalitythattheyimplement.

You’llseethatwe’veattachedtwovariablestothe$scopeobject.$scope.citiesisanarrayofcityobjects,eachwithanameandatimezone.$scope.selectedCityisareferencetothefirstiteminthecitiesarray.

Themagicstartstohappenwhenweswitchovertoourmarkup.Let’sopenuptheindex.htmlandaddsomethinglikethisinsidethe<body>:1<p>Helloworld!WelcometoTimezoneFinder.</p>

2<divng-controller="MainController">

Page 21: Front-End Fundamentals: A practical guide to front-end web development

3<label>Selectacity</label>

4<selectng-model="selectedCity"ng-options="city.nameforcityincities"></se\

5lect>

6<p>Thetimezonein{{selectedCity.name}}is{{selectedCity.timezone}}.</p>

7</div>

Wehaveusedseveralnewdirectiveshere.Firstly,weattachedMainControllertotheDOMusingngController.We’vethengota<select>elementthatimplementsngModelwhichsetsupdata-bindingbetweentheelement’sselectedoptionand$scope.selectedCity.Whenchoosingadifferentoption,thescopeobjectwillautomaticallyupdateanyotherplacewhereitisbeingused,suchasinthemessagebelowthe<select>element.Lastly,ngOptionsisadirectivespecificto<select>elements.Ifwerunourapplicationweshouldseesomethinglikethis:

Aninterestingpointtomentionhereiswe’veactuallyjustcoveredallpartsofanMVCarchitecturalpatternwithinAngular.Themodelsarethepropertieswesetonthe$scope.TheHTMLwithdata-bindingsthatwewroteareourviews,andthengControllerspecifiesourcontrollerfunctionthatcontainsourbusinesslogic.

RoutingAngularisexceedinglywellsuitedforbuildingSPAs.Angular‘routing’allowsyoutocreatemultipleviewsandhavethemloadedseparatelydependingontheURLpathbeingrequestedbytheclient.

RoutingfunctionalityisnotbakedintotheAngularJScorelibrary.ItisprovidedasaseparatemodulecalledngRoute.Justlikewhenweincludedthecorelibrary,wecanusetheCDNaddresstograbthefile.We’llupdateour<head>tolooksomethinglikethis:1<head>

2<metacharset="utf-8">

3<title>TimezoneFinder</title>

4<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.mi\

5n.js"></script>

6<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular-ro\

7ute.min.js"></script>

8<scriptsrc="./app.js"></script>

9</head>

NowwecanaddanewpagetoourapplicationwhichwilldemonstratehowroutingcanbeimplementedinAngular.Let’shavethenewpagedisplayalistofalltheavailablecitiesandtheirrespectivetimezones.Wecancallitthe‘FullList’page.We’llneedtocreateanewtemplate(i.e.anHTMLmarkupfile)forthepage.Createafilecalledlist.htmlintherootdirectoryandplacethismarkupinside:1<h1>FullList</h1>

2<ul>

3<ling-repeat="cityincities">

Page 22: Front-End Fundamentals: A practical guide to front-end web development

4 Thetimezonein{{city.name}}is{{city.timezone}}.

5</li>

6</ul>

That’sallweneedtoadd.Don’tworryabout<html>tagsoranythinglikethat.Thisfileisjustastubforothertemplatestouse.Now,dependingontheURLusedtoaccessthepage,wewillaskAngulartoincludethemarkupintoindex.html.Beforesettingupourrouting,let’salsocreateafilecalledwelcome.htmlintherootdirectoryandaddthefollowingfamiliarmarkup:1<h1>Welcome</h1>

2<p>Helloworld!WelcometoTimezoneFinder.</p>

3<label>Selectacity</label>

4<selectng-model="selectedCity"ng-options="city.nameforcityincities"></sele\

5ct>

6<p>Thetimezonein{{selectedCity.name}}is{{selectedCity.timezone}}.</p>

Let’smoveontotheindex.html.We’renowabletoremovethewelcomemarkupfrominsideour<body>:1<!doctypehtml>

2<html>

3<head>

4<metacharset="utf-8">

5<title>TimezoneFinder</title>

6<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.\

7min.js"></script>

8<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular-\

9route.min.js"></script>

10<scriptsrc="./app.js"></script>

11</head>

12<bodyng-app="timezoneFinderApp">

13<divng-view></div>

14</body>

15</html>

We’veaddedanewelementwiththengViewdirectiveattached.ThisdirectivetellsAngularwheretoincludethetemplatethatisrequiredforthecurrentroute(i.e.URLpath)beingaccessed.Whentheroutechanges,thedirectivewillautomaticallyupdatetheelementwiththecontentsoftherelevanttemplate.

NowwecanjumpovertoourJavaScriptfileapp.jstoaddthelogicforrouting.Firstofall,weneedtocreateadependencyonthengRoutemodule.Withoutdoingthat,we’reunabletousethefunctionalitythatthemoduleprovides.FormoreinformationonhowthisworksinAngular,checkouttheofficialdocumentationondependencyinjection.Addthedependencytothefirstlineofapp.js:1varapp=angular.module('timezoneFinderApp',['ngRoute']);

Nowlet’simplementourroutinglogic.We’lldothisinsideourmodulesconfigblock.Thismethodallowsustosetupconfigurationsforourmodulebeforeanycontrollersareexecuted:1varapp=angular.module('timezoneFinderApp',['ngRoute']);

2

3app.config(['$routeProvider',function($routeProvider){

4$routeProvider.

5when('/welcome',{

Page 23: Front-End Fundamentals: A practical guide to front-end web development

6templateUrl:'welcome.html',

7controller:'MainController'

8}).

9when('/list',{

10templateUrl:'list.html',

11controller:'MainController'

12}).

13otherwise({

14redirectTo:'/welcome'

15});

16}]);

17

18app.controller('MainController',['$scope',function($scope){

19...

Asyoucansee,we’veinjectedthe$routeProviderserviceintoourconfigblock.Then,usingthe$routeProvider.when()function,wewereabletodefineourcustomroutes.We’vesetuptworoutesforeachtemplatethatwehave.WhentheURLpathmatcheseitherofthoseroutedefinitions,itwillgrabthemarkupfromthetemplateUrlandplaceitinsidethengViewdirectivethatweplacedinsideindex.html.

WecanalsotellAngulartoloadaspecificcontrollerforeitherofourroutes.Thesedon’thavetobethesamebutforourapplicationexampleweonlyneedtoexecutetheMainControllercontroller.We’vealsoused$routeProvider.otherwise()toredirecttothewelcomepagewhennootherroutedefinitionismatched.Readthe$routeProviderdocumentationtolearnaboutalltheavailableoptions.

Ifweruntheapplicationagain,wemightnoticethattheURLupdatedtoincludethe/welcomeroutebecauseweaccessedthepagewithoutarouteandourredirectTokickedin.ThefullURLwillactuallylooksomethinglikehttp://localhost/TimezoneFinder/#/welcome.ThehashisaddedbyAngularbydefaultaspartofits$locationservicehashbangmodefunctionality.However,wecanturnontheHTML5modewhichisbasedontheHTML5HistoryAPIandthiswillremovethehash.PrettymuchallmodernbrowserssupportthisfunctionalityandAngularwillfallbacktousingthehashbangmodeforolderbrowsers.SeeCanIUseforafulllistofbrowsersupport.

Let’supdateourconfigblock:1app.config(['$routeProvider','$locationProvider',function($routeProvider,$loc\

2ationProvider){

3$locationProvider.html5Mode(true);

4$routeProvider.

5when('/welcome',{

6...

Now,whenweaccesstheapplicationviatherootURLweshouldberedirectedtothewelcomepagewithoutahashappearingintheURL.Note:Ifyouareaccessingtheapplicationinasub-directory(e.g.http://localhost/TimezoneFinder/)thenyouwillneedtoaddthe<base>tagtoyourindex.htmlinsidethe<head>asfollows:1<head>

2<metacharset="utf-8">

3<title>TimezoneFinder</title>

Page 24: Front-End Fundamentals: A practical guide to front-end web development

4<basehref="/TimezoneFinder/"/>

5...

Ok.Sotobeabletonavigatebetweentheroutes,let’saddanavigationmenutoourindex.html.1<bodyng-app="timezoneFinderApp">

2<ul>

3<li><ahref="welcome">Welcome</a></li>

4<li><ahref="list">FullList</a></li>

5</ul>

6<divng-view></div>

7</body>

Runtheapplicationagainandyou’llseethatwecannavigatebetweenthedifferentviews.AlthoughremovingthehashfromtheURLmakesthemlookpretty,youmightnoticethatifyoutrytoaccessadefinedroutedirectlythatyouwillreceivea404NotFounderrormessage.ThisisbecauseAngularisservingallofitsfilesthroughindex.htmlfile.You’llneedtoconfigureyourwebservertohandlerewrites.CheckoutthisveryusefulGithubwikipagethatexplainshowtodothisforvariouspopularwebserversoftware.

CustomDirectivesAngularprovidesawholebunchofusefuldirectivesoutofthebox.Youcangetprettydamnfarwithouteverneedingtowriteyourown.However,itcanbeveryusefultoknowhowtowriteyourowndirectives.Evenifyoudon’tplantouseacustomdirective,writingonemayhelpyouunderstandtheinnergoings-onofAngular.

Let’screateadirectiveforourTimezoneFinderapplication.Ifyoulookinsideourtemplatefiles,wearerenderingthemessageThetimezonein{{selectedCity.name}}is{{selectedCity.timezone}}.bothonthewelcomeandfulllistpages.Ifwewantedtochangethemarkupforthesemessages,wewouldhavetochangecodeintwoseparateplaces.Topreventthis,let’screateadirectivethatwillrenderthemessagewithinanyelementitisattachedto.

Wecanopentheapp.jsfileandaddthedirectiveblockasfollows:1app.directive('cityTimezone',function(){

2return{

3scope:{

4city:'=city'

5},

6template:'Thetimezonein{{city.name}}is{{city.timezone}}.',

7};

8});

9

10app.controller('MainController',['$scope',function($scope){

RememberthattheAngularstandardistonamedirectivesinlowerCamelCase.We’vecalledourdirectivecityTimezone.Itrequiresacitytobepassedasaparameter.ThetemplatemarkupisreturneddirectlybutyoucoulduseaseparatetemplateHTMLfileusingtemplateUrlifyouwantedto.

Returningtoourexample,let’saddthenewdirectivetoourtemplatefilesstartingwithwelcome.html:

Page 25: Front-End Fundamentals: A practical guide to front-end web development

1<h1>Welcome</h1>

2<p>Helloworld!WelcometoTimezoneFinder.</p>

3<label>Selectacity</label>

4<selectng-model="selectedCity"ng-options="city.nameforcityincities"></sele\

5ct>

6<pcity-timezonecity="selectedCity"></p>

Andthenoursecondtemplatefile,list.html:1<h1>FullList</h1>

2<divng-controller="MainController">

3<ul>

4<ling-repeat="cityincities"city-timezonecity="city"></li>

5</ul>

6</div>

Visittheapplicationagainandnothingwillhavechangedfromanenduser’sperspective.However,ifwewantedtoimprovethemessageoritsfunctionalityinthefuture,wenowonlyneedtochangecodeatasinglelocation.

Thereareplentyofotherconfigurationoptionsfordirectivessobesuretoreadtheofficialdocumentationtofindoutmore.

AdvancedItwouldbegreattocoverAngularinmoredepthbutthisisn’tanAngularbook.However,beforeusingAngularinyourownprojects,it’srecommendedthatyougainsomeunderstandingofthefollowing:

Services-Angularservicesaregreatforseparatingoutfunctionalitythatistobesharedthroughoutanapplication.Thereareendlessimplementations,suchasstoringlogged-inuserdetails,accessingexternalAPIsandothers.ReadtheServicesdocumentation.Filters-Angularfiltersareusedforformattingoutputbeforeitisdisplayedtousers.Theycanbeusedinvariouspartsofanapplicationandyoucanevenbuildyourown.ReadtheFiltersdocumentation.Testing-Getintothehabitofwritingunittestsasyouaddfunctionality;itcansaveyoualotoftimewhilstdebuggingandtestingyourapplicationasitgrows.You’llneedtolearnaboutsomeadditionaltoolsfortestingsuchasKarma,JasmineorProtractor.Formoreinformation,seetheunittestingandendtoendtestingdocumentationpages.

Ifyou’reseriousaboutlearningAngularJSthenthisawesomelistofeducationresourcesishighlyrecommended.

AnotherrecommendationtocheckoutisAngularJSBatarang,aChromeextensionfordebuggingandprofilingAngularapplications.

Backbone.js

Page 26: Front-End Fundamentals: A practical guide to front-end web development

Backbone.jsisanotherpopularJavaScriptframeworkforbuildingwebapplications.ItwascreatedbytheamazingmindofJeremyAshkenaswhoisalsothecreatorofCoffeeScript.Afairnumberoflarge-scaleapplicationshavebeenbuiltusingBackbonesuchasAirbnb,PinterestandSoundcloud.

OverviewBackboneisoftenreferredtoasalibraryratherthanaframeworksinceitplayswellwithotherJavaScriptlibrariesinsteadoftryingtoreinventtheJavaScriptobjectmodel.Backbonecomeswithfourcorecomponents:models,collections,viewsandrouters.ThecombinationofthesecomponentsmakeupthecorearchitectureofBackbonebutyoucanextendanyoftheirfunctionalitytomeetanapplication’srequirements.

Backboneisverylight.Theproductionminifiedversionofthelibrarycomesinatjustover6kb.Incomparison,AngularJSisover40kb.Notthata30kbdifferenceisanywhereneartheendoftheworldoranything,butitdoessaysomethingforthesimplicityofBackbone.However,BackbonerequiresUnderscore.js(5kb)andyoushouldincludejQuery(30kb+)tomakefulluseoftheHistoryAPIwithBackbone.RouterandDOMmanipulationinBackbone.View.

JustaswedidintheAngularJSsectionearlierinthischapter,we’regoingtolearnabitaboutBackbonebyusingittorebuildourapplicationexample,TimezoneFinder.Afterwe’veinstalledBackbonewe’regoingtointroduceeachofthecorecomponentsbyaddinganotherpiecetotheapplication.

InstallationJustaswithanyotherJavaScriptlibrary,itneedstobeincludedonthepage.Hereisasampleindex.htmlthatincludesaCDNversionofBackbone,itsharddependencyUnderscore.js,andsoftdependencyjQuery.Let’smakethisfilenowinourprojectroot:1<!doctypehtml>

2<html>

3<head>

4<metacharset="utf-8">

5<title>TimezoneFinder</title>

6<scriptsrc="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></\

7script>

8<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/unde\

9rscore-min.js"></script>

10<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbo\

11ne-min.js"></script>

12<scriptsrc="./app.js"></script>

13</head>

14<body>

15<p>Helloworld!WelcometoTimezoneFinder.</p>

16</body>

17</html>

Page 27: Front-End Fundamentals: A practical guide to front-end web development

We’vealsoincludedapp.jswhichwillstoreourcustomscripts.That’sit!NowwecancontinuetobuildTimezoneFinderagain,butthistimeinBackbone.

ModelsandCollectionsModelsinBackboneletyoudefineyourdatastructureandrelatedlogic.InourTimezoneFinderapplication,we’regoingtodisplaycitiesandtheirrelatedtimezones.SoitmakessensetohaveaCitymodelthatstoresitsnameandtimezone.

Setsofmodelsarecalled‘collections’.Soinourexampleapplication,we’regoingtocreateacollectionthatholdsasetofcities.Let’scallitCitiesCollection.

Let’sopenupapp.jsandaddthefollowingcode.1//Defineourmodelanddefaultvalues.

2varCity=Backbone.Model.extend({

3defaults:{

4id:'',

5timezone:''

6}

7});

8

9//Defineourcollection.

10varCitiesCollection=Backbone.Collection.extend({

11model:City

12});

13

14//Createourcollectionofcities.

15varcitiesCollection=newCitiesCollection([

16{id:'London',timezone:'GMT'},

17{id:'Tokyo',timezone:'JST'},

18{id:'Melbourne',timezone:'EDT'},

19{id:'LosAngeles',timezone:'PST'},

20{id:'NewYork',timezone:'EST'}

21]);

Noticetheextendfunction;you’llseethisbeingusedalotinBackbone’scorefunctionality.Intheabovecodesnippet,we’reusingittoextendthefunctionalityoftheBackbone.ModelandBackbone.Collectioncomponents.YoucanlookatextendastheBackbonewaytodefinepropertiesforthedifferentcomponentsofyourapplication.It’sworthnotingthatitsuseisnotrequired.IfwehadremovedtheextendfunctionfromBackbone.Modelthecodewouldstillworkbuttherewouldn’tbeanydefaultvalueswhenanewCityiscreated.

ViewsBackboneviewsgiveyouaplacetoorganizecoderelatedtoyourinterface.Theyletyouwritethelogicbehindthepresentationofmodeldatabutdon’tcontainHTMLmarkuporCSS.Backbonedoesn’treallyhavecontrollersfromthecommonMVCpatternbutinsteadviewsusuallycontainmuchofthatlogic.Therearenorestrictionsonhowyourenderyourviews.ItisrecommendedtouseaJavaScripttemplatingengine.Underscore.jshasitsowntemplatingenginewhichissimple,lightweightandperfectforourexampleapplication.YoucanalsolookintootheroptionssuchasMustacheorHandlebars.ToquoteEleanorRoosevelt,andnowtheSpidermanmoviescript,“Withgreatfreedomcomesgreat

Page 28: Front-End Fundamentals: A practical guide to front-end web development

responsibility.”YoumayfindyourselfwritingafairamountofboilerplatecodeforyourapplicationsinBackbonewhichmightbeseenasagoodthingbecauseitgivesyoufullcontrolandunderstandingofthelogicbehindyourapplication.

Let’sgoaheadandjumpbackovertoTimezoneFindertoimplementourfirstview.Openupindex.htmlandaddtheinitialmarkuptothe<body>tag:1<body>

2<divid="view"></div>

3</body>

The#viewelementwillberesponsibleforrenderingourview.Switchovertoapp.jsandappendthefollowingscripttothefile,andthentogetherwe’llgothroughwhatwe’veactuallydone:1//Thisviewrendersaselectelementcontainingthedifferentcities.Whena

2//cityisselectedamessageoutputstherelativetimezone.

3varSelectCityView=Backbone.View.extend({

4//ThisistheDOMelementtheviewwillberenderedwithin.

5tagName:'div',

6

7//Declaretemplatesrequiredforthisview.

8template:_.template(

9'<p>Helloworld!WelcometoTimezoneFinder.</p>'+

10'<label>Selectacity</label>'+

11'<selectid="cities"></select>'+

12'<pid="message"></p>'

13),

14

15option_template:_.template('<optionvalue="<%=id%>"><%=id%></option>'),

16

17message_template:_.template('<p>Thetimezonein<%=id%>is<%=timezone%>.\

18</p>'),

19

20//Thisisautomaticallycalledwhentheviewiscreated.

21initialize:function(){

22this.render();

23this.renderMessage();

24},

25

26//Rendersourviewandtheselectelement.

27render:function(){

28this.$el.html(this.template());

29_.each(this.collection.models,function(item){

30varoption=this.option_template(item.toJSON());

31this.$el.find('#cities').append(option);

32},this);

33returnthis;

34},

35

36//Renderstheselectedcitymessage.

37renderMessage:function(){

38varmessage=this.message_template(this.model.toJSON());

39this.$el.find('#message').html(message);

40returnthis;

41},

42

43//Listenstothe'change'eventonourselectelement.

44events:{

Page 29: Front-End Fundamentals: A practical guide to front-end web development

45"change#cities":"citySelected"

46},

47

48//Whenacityisselectedweupdatethemessage.

49citySelected:function(){

50varid=this.$el.find('#cities').val();

51this.model=this.collection.get(id);

52this.renderMessage();

53}

54});

55

56//WaitfortheDOMtobereadybeforecreatingourview.

57$(document).ready(function(){

58varselectCityView=newSelectCityView({

59collection:citiesCollection,

60model:citiesCollection.get('London')

61});

62$('#view').html(selectCityView.el);

63});

WestartedbydefiningSelectCityViewwhichcontainsourview.Aswedidwithmodelandcollection,weextendedaviewtoincludeallofourcustomlogic.Backboneviewsarequitesimpleandcomewithonlyahandfulofproperties.

AviewmustbeassociatedwithaDOMelement.Theelpropertyofaviewcontainsareferencetothiselement.Therearetwodifferentwaystoinitializeel.YoucancreateanewelementbyusingacombinationoftagName,classNameandidproperties.Alternatively,youcanreferenceanelementthatalreadyexistsinthepage.Inoursnippetabove,wespecifiedatagNamesothatanewdivelementwascreatedfortheview.

UsingtheUnderscore.jstemplatefunction,wehavesetupafewtemplatestobeusedwithinourviews.Templatescancontainplaceholdersandwecanpassinahashcontainingthevaluestopopulatethem.

Next,we’vegotinitialize.Thisisanoptionalpropertythatactsasaconstructorforourview.Itisrunautomaticallywhentheviewiscreatedsoyou’lloftenseeitbeingusedtocallrenderfunctions.

Thenexttwoproperties,renderandrenderMessagearefunctionsthatoutputourHTMLmarkup.We’veusedthemtodynamicallycreatethevariousselect<option>elementsandtheselectedcitymessage.It’scommonpracticetoplacereturnthisattheendofrenderfunctionssothatyoucanchainfunctionalitytogether,e.g.view.render().renderMessage().

Theeventspropertyallowsustobindtovariousevents.Inourexample,we’relisteningforthechangeeventonourselectelement.Forthefullcatalogofavailableevents,seetheofficialdocumentation.WhenachangeisdetectedwecallourcustomcitySelectedfunctionwhereweusejQuerytoreturntheselecteditemsvalue,updatethelocalmodelvariabletocontaintheselectedcityandthenre-renderourmessagebycallingrenderMessage().

Lastly,wewrappedtheactualcreationofourviewina$(document).ready.Wedidthisbecauseour<script>tagsareinthepage<head>andwouldcauseourJavaScripttocompilebeforetheDOMisready.Alternatively,youcanplaceyour<script>tagsjust

Page 30: Front-End Fundamentals: A practical guide to front-end web development

before</body>tohavethembecalledlaterinthepagelifecycle.Asmentionedearlier,theelpropertycontainsareferencetotheDOMelementforourview.Sowe’reabletousejQuerytopopulate#viewwithourviewsrenderedHTML.

RoutersInBackbone,youareabletoutilizeBackbone.RoutertoconnectURLstoactionsandeventsinapplications.MostbrowsersnowsupporttheHistoryAPIbutforthosethatdon’t,theroutergracefullyfallsbacktousinghashfragmentsinstead.

Formostapplications,you’llusuallyonlyneedtohaveonerouter.Inourexample,let’sgoaheadanddefineourrouterinapp.js:1//DefinesourRouterwhichisresponsibleforhandlingtheswitchingbetween

2//ourvariouscontentviews.

3varAppRouter=Backbone.Router.extend({

4routes:{

5'':'showWelcome',

6list:'showList'

7},

8

9showWelcome:function(){

10varselectCityView=newSelectCityView({

11collection:citiesCollection,

12model:citiesCollection.get('London')

13});

14this.showView(selectCityView);

15},

16

17showList:function(){

18varcityListView=newCityListView({

19collection:citiesCollection

20});

21this.showView(cityListView);

22},

23

24showView:function(view){

25if(this.currentView){

26this.currentView.remove();

27this.currentView.unbind();

28}

29

30this.currentView=view;

31$('#view').html(this.currentView.el);

32}

33});

Theroutespropertycreateskey-valuepairingsforthevariousapplicationroutesintheformatpath:'callback'.Ourdefaulthomeroute(i.e.definedas'')willcallshowWelcomewhichinturnwillrenderSelectCityView.We’vealsoaddedalistroutethatwillrenderanewviewcalledCityListViewwhichwe’llcreateinamoment.Tomakethingsalittlemoresimple,we’vecreatedahelperfunctioncalledshowViewthatmanageswhichviewiscurrentlybeingdisplayed.Wealsohavetodestroyviewswhenchangingbetweenthemtopreventmemoryleaksandbindingeventsmultipletimes.

Let’screatethatmissingCityListViewinourapp.js:

Page 31: Front-End Fundamentals: A practical guide to front-end web development

1//Thisviewrendersalistofallcitiesandtheirtimezones.

2varCityListView=Backbone.View.extend({

3tagName:'div',

4

5template:_.template('<h1>FullList</h1>'+

6'<divid="list"></div>'

7),

8

9message_template:_.template('<p>Thetimezonein<%=id%>is<%=timezone%>.\

10</p>'),

11

12initialize:function(){

13this.render();

14},

15

16render:function(){

17this.$el.html(this.template());

18_.each(this.collection.models,function(item){

19varmessage=this.message_template(item.toJSON());

20this.$el.find('#list').append(message);

21},this);

22returnthis;

23},

24});

IncomparisonwithSelectCityView,thisviewshouldbefairlyself-explanatory.Itrendersalistofmessagesforeachofthecitiesinourcollection.

Nowthatwehavearouterandbothviewsincode,we’regoingtoneedtohaveawaytoswitchbetweentheviews.Let’saddasmallmenutoourindex.html:1<body>

2<ulid="menu">

3<li><ahref="/">Welcome</a></li>

4<li><ahref="/list">FullList</a></li>

5</ul>

6<divid="view"></div>

7</body>

Thelastpieceofthepuzzleistoupdateour$(document).readyfunction:1//WaitfortheDOMtobereadybeforecreatingourview.

2$(document).ready(function(){

3Backbone.history.start({

4pushState:true

5});

6

7//CreateourRouterandautomaticallyshowthewelcomeview.

8varappRouter=newAppRouter;

9appRouter.showWelcome();

10

11//Capturemenuitemclickstotriggerroutechanges.

12$('#menua').click(function(e){

13e.preventDefault();

14appRouter.navigate($(this).attr('href'),{trigger:true});

15});

16});

WecallBackbone.history.starttoroutetheinitialURLandstartlisteningforroutechanges.ThisisrequiredforustosetuproutingwithpushStatefunctionality.Next,we

Page 32: Front-End Fundamentals: A practical guide to front-end web development

createtherouterandcallshowWelcomesothatviewisdisplayedbydefault.Lastly,we’relisteningtoclicksinourmenuandcallingnavigatetochangetheroute.

That’sit!We’vesuccessfullycreatedourapplicationinBackbone.TakeitforaspinonyourlocalwebserverandyoushouldnoticeverysimilarresultstotheapplicationthatwecreatedintheAngularJSsectionearlierinthischapter.

We’veonlytouchedthesurfaceofwhatispossiblewithBackbonebuthopefullythetakeawayfromyourbriefencounterispositive.Althoughthereisalearningcurve,it’sanextremelypowerfulJavaScriptframeworkthatgivesyouplentyoffreedomtoscale.Ifyou’dliketolearnmoreaboutBackbone,DevelopingBackbone.jsApplicationsbyAddyOsmaniisstronglyrecommended.Also,youmightbeinterestedintheBackboneDebuggerChromeextensiononceyougetstartedbuildingBackboneapps.

Thefinalpopularframeworktointroducetoyouinthischapteris‘Ember’.

Ember

Ember.jsisanotheropen-sourceJavaScriptframeworkwhichwasoriginallycreatedbyYehudaKatzandTomDalein2011.Althoughit’sthelastframeworkcoveredinthischapter,it’sbynomeanstheleast.Withastrongcommunityandabrilliantarchitecturalpattern,Emberisthechoiceframeworkformanydevelopers.

OverviewThecoreoftheEmberarchitecturelieswithintheURL.QuotingfromtheEmbercoreconcepts:

“It’simportanttorememberwhatmakesthewebspecial.ManypeoplethinkthatsomethingisawebapplicationbecauseitusestechnologieslikeHTML,CSSandJavaScript.Inreality,thesearejustimplementationdetails.Instead,thewebderivesitspowerfromtheabilitytobookmarkandshareURLs.URLsarethekeyfeaturethatgivewebapplicationssuperiorshareabilityandcollaboration.Today,mostJavaScriptframeworkstreattheURLasanafterthought,insteadoftheprimary

Page 33: Front-End Fundamentals: A practical guide to front-end web development

reasonfortheweb’ssuccess.Ember.js,therefore,marriesthetoolsandconceptsofnativeGUIframeworkswithsupportforthefeaturethatmakesthewebsopowerful:theURL.”

Becauseofitsstronglyopinionatedarchitecture,manypeoplefindEmbereasiertolearn.Itmayalsobemorestraightforwardbecauseoftheexcellentofficialdocumentation.

ItisworthnotingthatEmberhasadependencyonHandlebars.Soifyouwerehopingtouseanothertemplatinglanguage,youmayneedtolookelsewhere.You’llalsoneedjQuery,butwhat’snewright?

JustaswedidwithAngularandBackbone,let’sgoaheadandrebuildourTimezoneFinderapplication,butthistimeinEmber!

InstallationWe’llcreateindex.htmlinourapplication’srootdirectoryandincludetheEmberlibraryanditsdependencies:jQueryandHandlebars:1<!doctypehtml>

2<html>

3<head>

4<metacharset="utf-8">

5<title>TimezoneFinder</title>

6<scriptsrc="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></\

7script>

8<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/hand\

9lebars.min.js"></script>

10<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/ember.js/1.9.0/ember.min\

11.js"></script>

12<scriptsrc="./app.js"></script>

13</head>

14<body>

15<p>Helloworld!WelcometoTimezoneFinder.</p>

16</body>

17</html>

ForfutureprojectsyoumaybeinterestedincheckingouttheStarterKitofferedontheEmberhomepagewhichprovidesyouwithabarebonesstartingpointforyourapplication.However,forTimezoneFinderwe’lljustcreateeverythingourselves.

We’llcreateanapp.jsfileandaddthefollowingsinglelinetogetstarted:1App=Ember.Application.create();

EveryEmberapplicationhasonlyoneEmber.Applicationobject.SowhenusingEmber,beforeyoudoanythingelseyouhavetocallcreate.

RouterAsexplainedearlier,theURLisacoreconceptofEmber’sarchitecture.Bydefault,Embercreatesanindexroutewhichmapsto/(i.e.theroot).Soforourapplicationwe’llonlyneedtocreateoneextrarouteforourFullListpagewhichlistsallcitiesandtheirtimezones.Let’sappendthefollowingtoourapp.js:

Page 34: Front-End Fundamentals: A practical guide to front-end web development

1App.Router.map(function(){

2this.route("list");

3});

UsingApp.Routerweareabletomapasmanyroutesaswewant.We’venamedourroutelistwhichmeansthat,bydefault,itspathwillbe/list.Emberalsosetsupseveralothercomponentsautomaticallyforeachroutecreatedandthesewillbeintroducedaswedivedeeperintotheapplication.

TemplatesTemplatesareresponsibleforpresentingthemarkupfortheuserinterface.EmbertemplatesareexclusivelywritteninHandlebarssoyouwillbenefitfromspendingsometimegettingfamiliarwiththeirsemanticsbeforebuildingyourownreal-worldapplication.

Returningtoourexample,we’llstartbyaddingthenavigationmenutothetopoftheapplication.We’regoingtoaddourtemplatesdirectlytoourindex.html:1<body>

2<scripttype="text/x-handlebars">

3<ulid="menu">

4<li>{{#link-to'index'}}Welcome{{/link-to}}</li>

5<li>{{#link-to'list'}}FullList{{/link-to}}</li>

6</ul>

7</script>

8</body>

UsingtheEmberHandlebarslink-tohelperit’seasytocreatelinkstothevariousrouteswithinanapplication.Inourexamplewe’veaddedalinktothefrontpagerouteindexandourcustomlistroute.Nowlet’ssetupthetemplatesforeachofthoseroutes.

WhenrequestingtheURLforaroutemappedinApp.Router,EmberwillautomaticallylookforaHandlebarstemplatetodisplayforthatroute.Let’saddatemplateforbothindexandlistroutes,again,inourindex.html:1<scripttype="text/x-handlebars"id="index">

2<h1>Welcome</h1>

3<p>Helloworld!WelcometoTimezoneFinder.</p>

4</script>

5

6<scripttype="text/x-handlebars"id="list">

7<h1>FullList</h1>

8</script>

We’vesetthe<script>element’sidattributetomatchtheroutename.Butbeforethiswillwork,wehavetocreatesomethingcalledanoutlet.Theoutlethelpertellstheapplicationwheretorenderthetemplatethatwaspickedforaspecificroute.Let’saddtheoutlethelpertoourindex.htmljustbelowthenavigationmenu:1<scripttype="text/x-handlebars">

2<ulid="menu">

3<li>{{#link-to'index'}}Welcome{{/link-to}}</li>

4<li>{{#link-to'list'}}FullList{{/link-to}}</li>

5</ul>

6

7{{outlet}}

Page 35: Front-End Fundamentals: A practical guide to front-end web development

8</script>

9...

Now,whenaccessingtheapplicationyou’llbeabletoswitchbetweenthetwotemplatesusingthelinksinthenavigationmenu.Thatwasprettyquickandeasyright?Let’sstartaddingsomelogictoourapplication.

ModelsEachtemplateisbackedbyamodel.Modelsareobjectsthatcontaindatatobedisplayedtotheuserviathetemplate.ThemostcommonuseofamodelistolinkituptoanAPIsothatyou’regettingdatadirectlyfromaservice,butforthepurposeofTimezoneFinderwe’rejustgoingtodefineourmodeldatalocally.Let’sappendacitiesvariableinourapp.jsfilesothatitcanbeusedthroughoutourapplication:1varcities=[

2{name:'London',timezone:'GMT'},

3{name:'Tokyo',timezone:'JST'},

4{name:'Melbourne',timezone:'EDT'},

5{name:'LosAngeles',timezone:'PST'},

6{name:'NewYork',timezone:'EST'}

7];

Next,we’regoingtotellEmberthatwewanttousecitiesasthemodelforbothourindexandlistroutetemplates.ThewaytodothisistocreateaRouteobject.Thatcanbealittleconfusing,butjustrememberthataRouteobjectisnotthesameasaroutedefinedinyourRouterobject.Again,we’llappendthefollowingtoourapp.js:1App.IndexRoute=Ember.Route.extend({

2model:function(){

3returncities;

4}

5});

6

7App.ListRoute=Ember.Route.extend({

8model:function(){

9returncities;

10}

11});

NowthatEmberknowswhichmodeltoprovideourroutetemplateswith,wecanswitchbackovertoindex.htmlandupdateourHandlebarstemplates:1<scripttype="text/x-handlebars"id="index">

2<h1>Welcome</h1>

3<p>Helloworld!WelcometoTimezoneFinder.</p>

4<label>Selectacity</label>

5{{view"select"content=modeloptionValuePath="content.name"

optionLabelPath="\

6content.name"selection=selectedCity}}

7<p>Thetimezonein{{selectedCity.name}}is{{selectedCity.timezone}}.</p>

8</script>

9

10<scripttype="text/x-handlebars"id="list">

11<h1>FullList</h1>

12<ul>

13{{#each}}

14<li>Thetimezonein{{name}}is{{timezone}}.</li>

Page 36: Front-End Fundamentals: A practical guide to front-end web development

15{{/each}}

16</ul>

17</script>

Forourindexroute,we’reusingtheEmber.Selectviewclasswhichrendersa<select>elementforus.We’veexplicitlysettheoptionstobepopulatedfrommodelwhichisdefinedinApp.IndexRoute.Aseachiteminourcitiesmodelisanobject,we’vehadtoexplicitlysettheoptionvalueandoptionlabel.TheselectedvaluewillbestoredinselectedCitysothatweuseittopopulateamessagebelowour<select>element.

Forthelistroute,itisveryeasytoiterateoverthemodelobjectandoutputeachcity’spropertiesusingtheHandlebarseachhelper.

ControllerSomethingthatcantakealittlewhiletounderstandisthatalthoughtemplatesgettheirvaluesfrommodels,acontrollerliesbetweenthem.Thecontrollerisresponsiblefor‘decorating’amodelwithdisplaylogicbeforeitsvaluesarepassedtothetemplate.Bydefault,thecontrollerbetweenamodelandatemplatesimplypassesthroughthedata.Inourexample,thisisthecasewithboththeindexandlistroutes.Wedidn’tcreateanycontrollersbecausewedidn’tneedtodecorateoralterthedata.Theimportantpointtorememberhereisthattemplatesreceivealloftheirdatafromcontrollersandnotmodels.

Althoughwedon’tneedtoimplementcontrollersinTimezoneFinder,thissimplediagramtakenfromtheofficialdocumentationsumsuptheconceptquitenicely:

Advanced

Page 37: Front-End Fundamentals: A practical guide to front-end web development

ThereisplentymoresophisticationtoEmberthanwastouchedonhere.Aspreviouslymentioned,goandcheckouttheirexcellentdocumentationifyou’reinterestedinlearningmore.JustaswithAngularandBackbone,thereisapopularChromeextensionthatyoucanusetodebugyourEmberapplication.CheckoutEmberInspectorformoredetails.

SummaryHopefullythischapterwasasenjoyabletoreadasitwastowrite!Allthreeofthepopularframeworksintroducedinthischapteraregreatfuntoworkwith.Eachofthemhelpyoutothinkaboutdevelopingyourapplicationinasmartwaythroughmaintainableandscaleablecode.We’veonlylookedatthreeframeworksbutthereareplentymoreoutthereinthewildthatyoumaycomeacrossinyourtravels.Again,youcanfindthesourcecodeforthevariousversionsofTimezoneFinderavailablehere:https://github.com/fender/TimezoneFinder

Sothenextquestionyou’reprobablygoingtoaskis,‘whichisthebestframeworkformyproject?’That’ssomethingonlyyouareabletoanswerreally.Eachprojectisdifferentandwhenpickingaframeworkyouneedtoconsideryourspecificrequirements.Hereareafewrecommendedthingstothinkabout:

Whichframeworksmeetsyourrequirements?Forexample,ifyouspecificallydonotwanttouseHandlebars,thenyoucanruleoutEmber.Or,ifyoudon’twanttousejQuery,youmaywanttoconsiderAngular.Aswithanyapplicationyoubuild,you’regoingtoneedhelp.Sodosomeresearchtoseehowactiveandmaturetheframeworkis.Arethereregularupdates?Howbigisthecommunity?Aretheregoodresourcesforfindinganswerstocommonproblems?Tryit!Often,thebestwaytofindoutifsomethingisrightforyourprojectistotryitfirst.Youmightfindoneframeworkcomplimentsthewayyouthinkanddevelopmorethananother.CheckoutTodoMVC.Thisisaveryusefultoolthatoffersthesameto-doapplicationinalargenumberofdifferentframeworksforyoutocompare.ItwascreatedbyAddyOsmaniwhoalsowroteabrilliantarticleonselectingaframework:JourneyThroughTheJavaScriptMVCJungle.

Page 38: Front-End Fundamentals: A practical guide to front-end web development

Styling

Stylingyourmarkuponthefront-endisprettystraightforwardonthesurface.YouhaveaselectorinyourDOMandyouwantittolookacertainwayandusingthedescriptivelanguageofCSS,youtellitso.Thechallengemanynewfront-enddevelopersfaceisn’tgenerallyduetothecomplexityofCSSitself,it’sthenatureofCSSthatcanmakeitsochallenging.

TheCinCSSstandsfor‘cascading’,meaningthatstylesappliedtooneelementareinheritedbyotherelementsfurtherdowntheDOMtree.Ifyouapplyafont-sizetoyourdocument’s<body>andthenlookatthefont-sizeofsome<li>furtherdowntheDOM,you’llnoticethey’rethesame.Thefont-sizewasinherited.ThiscascadingnatureisboththebestandmostfrustratingfeatureofCSS.

Manytimes,you’llwanttostylesomethinglikeanitemlist,<ul>,thesameway,nomatterwhereitappearsintheDOM.Easy!Butwhenthedesignyou’retryingtoimplementhasdifferentvariationsofanelementbasedonwhereitappears,youmaystartrunningintospecificityproblems.

SpecificityinCSSisactuallyanintendedfeatureofthelanguage.Forexample,ifwewantedourallofouritemlistelementsinafootertohaveafewpixelsofmarginontheleftside,wesimplyneedtobemorespecificaboutourselector.Whatstartedoutas:1ul{margin-left:10px;}

Wouldbecome:1.footerul{margin-left:10px;}

Now,ifwewantallofouritemlistsinadifferentparentelementtohavenomarginatallthenwecandothesamething:1.blockul{margin-left:0;}

KeepingthosetwoCSSselectorsinmind,whathappenswhenwehavethefollowingmarkup?1<body>

2<divclass="block">

3<h1>HelloWorld!</h1>

4</div>

5<footerclass="footer">

6<divclass="block">

7<ul>

8<li>Listitem</li>

9<li>Listitem</li>

10</ul>

11</div>

12</footer>

13</body>

Page 39: Front-End Fundamentals: A practical guide to front-end web development

Intheexampleabove,the<ul>isstyledentirelybythecascade.Ifwedeclared.footerullast,the<ul>hasmargin,ifwedeclared.blockullast,the<ul>hasnomargin.Thereasonforthisisthatbothselectorshavetheexactsamespecificity,andCSSfallsbacktothecascadeapplyingthelastthingdeclaredthatmatchesourselectors.Tofurthercomplicatetheissue,differenttypesofselectorshavedifferentlevelsofspecificity.Forinstance,thethreemostcommonselectortypesfollowthisorderofspecificity:

1. element(leastspecific)2. class3. id(mostspecific)

Inourexampleabove,divulwouldalwaysbeoverriddenby.footerulbecausetheclassismorespecificthantheelement,eventhoughdivulhasamatch.

Soifwe’reawareofhowallthisworks,whyisCSSsuchatroublespotinfront-enddevelopment?Usuallytheanswertothatcomesfromacoupledifferentsources.

Firstly,thelargerapageisthemoreopportunityforselectorconflictsthereare.It’stoughtoknowjustwhereeverythingonapagemightappear,sowhenwe’refacedwiththeneedtohaveaninstanceofaselectorstyledjustso,thefirstthingmanyfront-enddevelopersdoisgetmorespecificandaddanewstyledeclaration.Ifthatgetsoverriddenbysomethingevenmorespecificorlowerinthecascade,theeasiestoptionistothrow!importantonthestylethatseemstoodifficulttooverride.Thatcausesfrustrationdowntheroadwhenachangecomesinthatneedstoaffectsomething,includingthethingthatwasoverwritten.Largely,thisproblemcanbesolvedwithproperplanning(ifyouhavethatluxury)orbychoosinganauthoringmethodologytominimizefuturefrustration(moreonthatlater).

Secondly,themorepeoplewhoareinyourcodebasewritingstyles,themoreopportunitiesforconflictandduplicationthereare.Morepeople,moreproblems.Johnnymightbeabletomakethestylingadjustmentsheneedsonewaywithouteverknowingthathe’stotallymangledthestylesforsomethingCarlwroteearlier.Thisproblemboilsdowntocommunication.Likethefirstissue,thiscanbesomewhatsolvedbyplanningorchoosingamethodologylikeBEM,butdocumentation,andevenwritingtestsforyourCSSwhichrunautomatically,canbeequallyasuseful.

ResponsiveWebDesignInthelastcoupleofyears,therehasbeenanexplosioninthepopularityofthisterm.Sowhatdoesitmean?Ifyou’renewtotheworldoffront-enddevelopment,youmaynothaveafullygraspedit.Inshort,ResponsiveWebDesign(RWD)istheconceptthatpagedesignsshouldbeflexibleandshouldaccommodateanyscreensize.Whetherit’syourmobilephoneoryourTV,thepageshouldadaptandthecontentshouldbereadilyviewableandaccessible.

Thetaskofactuallyfiguringouthowalayoutshouldadjustandchangetoaccommodatevariousscreensisoftenadesigner’sjob,butthetaskofmakingthoseflexiblelayoutsarealityfallstoafront-enddeveloper.

Page 40: Front-End Fundamentals: A practical guide to front-end web development

Responsivewebdesignisahumongoustopicandtherearelotsoftipsandtricksandmethodsformakingitallhappen.Solet’sgooversomeofthebasicthingsyou’llprobablywanttounderstandtogetstarted.

MediaQueriesAmediaqueryisastatementthatlimitsthescopeofyourstylestoaparticularmediatype(likescreenorprint)and/oramediafeature(likemin-widthorheight).Thisisreallyimportanttounderstandwhenyou’regettingintotheworldofRWDbecausetheygiveyouthepowertochangeyourstylesbasedoncertainconditions.

Amediaquerycanbeappliedasanattributeonthe<link>elementthatimportsyourstylesheet:1<linkrel="stylesheet"href="/path/to/your/style.css"media="(min-width:400px)">

Usingthismethod,yourstyle.cssstylesheetwillonlybeusedwhenthewidthofthepageis400pxorgreater.

Youcanalsousemediaqueriesdirectlyinyourstylesheetsaswrappersaroundablockofselectors:1.foo{

2color:blue;

3}

4

5@media(min-width:400px){

6.foo{

7color:green;

8}

9}

Intheabovestatement,.foowillbecoloredblueuntilthepagewidthis400pxorgreater.Oncethepagewidthhits400px,thecolorof.foowillchangetogreen.

Mediaqueriescanbechainedtogetherusingandtoincreasespecificity.Thisnextmediaquerymakessurethatstyle.cssisusedonlywhenthepageisbeingviewedonascreenandthewidthisbetween400pxand601px:1<linkrel="stylesheet"href="/path/to/your/style.css"media="screenand(min-wid\

2th:400px)and(max-width:600px)">

Thatsamemediaquerywritteninthestylesheetwouldlooklikethis:1@mediascreenand(min-width:400px)and(max-width:600px){

2/*yourstyles*/

3}

Youcanalsoseparatemediaqueriesbyusingacommatorepresent‘or’.Thismediaquerywillapplystyle.csswhentheorientationislandscapeorthepageisatleast400pxwide:1<linkrel="stylesheet"href="/path/to/your/style.css"media="(orientation:lands\

2cape),(min-width:400px)">

YoucanfindadetailedaccountofmediaqueryfeaturesandtypesattheMozillaDeveloperNetwork.

RelativeUnits

Page 41: Front-End Fundamentals: A practical guide to front-end web development

Agooddealofthevisualflexibilityofelementsonapagecomesfromdefiningtheirdimensionsnotwithpixels,butwithrelativeunits.Haven’theardofrelativeunits?Fearnot,here’saquickoverviewoftheunitsyou’llseeusedmostoften.

emandremUnits

Theemunitrepresentsthevalueofthefontsizeofthecurrentelement’sparent.Takealookatthefollowingexample:1.form{

2font-size:16px;

3}

4

5.forminput{

6width:2em;

7}

Whatwouldthewidthof.forminputbe?That’sright,32px,or2xthefontsizeof.form.emunitsarescalable,sowhenauserzoomsinwiththeirbrowseranythingstyledwithanemunitwillscaleproportionally.

Theremunitisabitnewer,andrepresentstherootfont-sizeofthedocument,whichisthefontsizeseton<html>.Whywouldyouwantsuchaunit?Well,aproblemthatoftencropsupwhenusingemunitsisasortofnestingmess.Hereisanotherexampletodemonstrate:1html{

2font-size:16px;

3}

4

5.forminput{

6width:2em;

7}

8

9.forminputspan{

10width:2em;

11}

Youmaythinkthatthewidthof.forminputspanwouldalsobe32pxbutactuallyitis64px.However,ifweswitchedoutemforremunitsthenbothwidthswouldindeedbe32px.Usinganremunitcankeeptextscalableandprovideasanebasefornestedems.

%Units

Usinga%valueworksinthewayyou’dexpect.Ifyouhaveanelement’swidthsetto100%anditsparentwidthis200px,yourelement’swidthisalsogoingtobe200px.ThisisaprettycommonwaytodefinedimensionsintheRWDworld.Ifyoudefinethemajorityofyourdimensionswithpercentagesratherthanabsolutepixelvalues,you’llbewellonyourwaytocreatingflexiblepages.

vwandvhUnits

Thesetwounitsarealsorelativelynewinthefront-endspaceandareveryhandyindeed.Theyfunctionsomewhatsimilarlytothe%unit,butinsteadofbeingbasedontheirparentstheyarebasedonthe‘viewport’(thedimensionsofthebrowserwindow).1vwisequalto1/100thofthecurrentviewportwidthand1vhisequalto1/100thofthecurrentviewport

Page 42: Front-End Fundamentals: A practical guide to front-end web development

height.Ifyouwantedtohaveanelementbeexactlytheheightoftheviewport,youcouldsetitsheightto100vhwhichequatesto100%oftheviewportheight.

Thereareahandfulofotherreallyinterestingrelativeunitsoutthere,butyou’lltypicallydealwiththeonespresentedaboveinourdaytodaywork.Ifyou’reinterestedinmoredetailsaboutalltherelativeunitsandtheirsupportinvariousbrowsers,checkouttheMozillaDeveloperNetwork.

SummaryBuildingfront-endapplicationswithRWDprincipalscangetprettycomplicated.Wrappingyourheadaroundemand%unitscanbetricky,andgettingeverythingonthepagetolookrightallthetimecanbeapainstakingprocess.Tobehonest,itwasabitofastruggletofigureoutwhat,ifanything,shouldbesaidaboutresponsivewebdesigninthisbook.Thetopicismassive,heavilydebated,andconstantlyevolving.Butsomethingneededtobesaidtobringnewerfront-enddevelopersuptospeedonwhatitisifnotexactlyhowtoimplementit.ThattopicisworthyofanentirebookitselfandtherejustsohappenstobeafantasticonewrittenbyEthanMarcottesimplytitledResponsiveWebDesign.YoucanfindthisseminalworkatABookApartinbothpaperbackandebookforms.

AuthoringMethodologiesA‘methodology’isagroupofproceduresforaccomplishingsomethingand,particularlyifyou’reworkingwithateam,somethingthatisincrediblyhelpfulwhenauthoringCSSforyourproject.Choosingorevencraftingyourownmethodologyisaperfectwaytokeeppeoplefromsteppingoneachother’stoesinthecodebase(mostly)andittakessomeofthe“HowthehelldoIdothis?”thinkingoutoftheequationaswell.

Sowhatexactlydowemeanwhenwetalkabout‘authoringmethodologies’forCSS?Generally,wemeanadocumentedstrategyforhowourcodewillbeorganizedandhowwe’llapproachstylingsomething.WillweuseIDselectorsforeverymajorsection?Shouldwetotallyignorethecascadetoavoidspecificityproblems?Howshouldwenameourclasses?Thesearethekindsofthingschoosingamethodologyisallabout.

Unfortunately,nobodycanjusttellyouwhichmethodologyisthebest.There’snorightanswer.Everysingleprojectwilllikelyhavedifferentneedsandthoseneedshavetobeanalyzedbeforeyoucanbegintothinkofhowtoapproachmeetingthem.Moreover,thereisnoonesinglemethodologythatcaneverbeperfectlyadheredto.Therewillalwaysbeexceptionstowhateveryoudecidetodobut,ifyoudocumentthoseexceptionsasyoucomeacrossthem,theirimpactonthewholeoftheprojectisusuallyprettyminimal.

Belowaretwocommonmethodologies,groupedbyhowtheauthorsperceivethespiritofthosemethodologies.

ComponentsandPatternsAcomponentbasedmethodologycentersaroundtheideathatcertainindividualchunksofstylescanbegrouptogethertoforma‘component’.ThesecomponentsshouldtypicallybepresentedtheexactsamewaynomatterwheretheyappearintheDOM.Agoodexample

Page 43: Front-End Fundamentals: A practical guide to front-end web development

ofthismightbeasmallupcomingeventscalendarwhichshouldalwayslookthesame,whetherinthefooterorasidebar.Let’swriteitup:

Markup1<divclass="calendar-component">

2<ul>

3<li>Jan<span>01</span></li>

4<li>Feb<span>29</span></li>

5</ul>

6<ul>

7<li>NewYear's!</li>

8<li>LeapDay!</li>

9</ul>

10</div>

CSS1.calendar-component{

2width:400px;

3}

4.calendar-componentul{

5width:60%;

6display:inline-block;

7padding:0;

8}

9.calendar-componentul:first-child{

10width:30%;

11}

12.calendar-componentli{

13list-style:none;

14}

15.calendar-componentspan{

16font-weight:bold;

17}

Thatisn’texactlythemostbeautifulcomponentontheweb,butit’scompletelyselfcontained.Nothingwehavewrittenabovewillaffectanythingthatisn’tdirectlyrelatedtoourcalendarcomponent.Ourcomponentmaystillbeaffectedbymoregenericstyles(likeour<ul>declarationsearlierinthischapter),butifweseparatethevariouspartsofourdesignsintotheseuniquecomponentsrightfromthebeginningofaproject,thenwecanpreventthatfromhappening.

Takingthisastepfurther,let’snowimaginewehaveanidenticallystyledside-by-sidelistcomponent.Itcontainssimilarlyformattedcontent,butinsteadofacalendarit’saT-shirtsizingchart.Thesimplestoptionwouldbetoduplicateourmarkupforthatcomponent,classesandall,withthedifferentcontent.Blamo!We’vejustcreatedare-usableCSSpattern.

Now,calendar-componentisn’texactlythemostgenericnametobeapplyingtoaT-shirtsizingchart,sofordevelopersanityit’srecommendedthatyoutrytogeneralizecomponentnamessotheycanbere-usedandunderstoodmoreeasily.ReducingduplicatedCSSisprettyimportantduetothenatureofthecascadeandthetendencyforstylestoshowupinoddplaces.IfyourprojecthappenstosupportInternetExplorer6-9thenduplicationcanbeevenmoreimportanttoavoidbecauseIEhasa4095totalselectorlimit-andthenitjuststopsreadingthem.

Page 44: Front-End Fundamentals: A practical guide to front-end web development

BEM

BEMisapopularcomponentwritingmethodologydevelopedbyYandexthatis,inmanyways,similartotheobjectorientedprogrammingmethodologyusedinotherlanguages.BEMstandsfor‘block’,‘element’and‘modifier’;thesearethecategoriesyourCSSselectorswillfallinto.Blocksarethelargestchunkofstylesthatmakeupaparticularvisualelementonapage.Elements,inregardstoBEM,aresub-sectionsofaparticularblock,andmodifiers,asyoumightguess,describeanyvariationsofaBEMblockorelement.

TheBEMmethodologyitselfisn’tlimitedtoCSSsinceit’salsoapplicableforXML,JSON,andprobablyotherthings,butwe’remostlyconcernedwiththeCSSusage.

Ourcalendarcomponent,describedabove,wouldequatetowhatBEMcallsablockwhiletheinnerHTMLwouldbeourelement.

ThetypicalpatternfornamingclassesusingBEMistoincludeourblocknameineveryselectorandnameeachelementoftheblockusing__toseparatethem.Modifiersaredenotedby--.

UsingBEMourCSSmightlooksomethinglikethis:1.calendar-component{

2width:400px;

3}

4.calendar-component__list{

5width:60%;

6display:inline-block;

7padding:0;

8}

9.calendar-component__list:first-child{

10width:30%;

11}

12.calendar-component__list-item{

13list-style:none;

14}

15.calendar-component__day{

16font-weight:bold;

17}

WhencomparingthevisualdisplayoftheblocktoourCSSselectors,itisallperfectlyclearataglancewhatstylesareaffectingwhatpieces.

Ifwelookatthatthirdselector.calendar-component__list:first-childyoumightnoticethatit’stheperfectopportunitytousewhatBEMcallsamodifiersinceallit’sreallydoingismodifyinganotherwiseperfectlynormal.calendar-component__list.

BEMconventionwouldbetocreateadifferentclassandapplyittothetheelementthatvariesfromitscompanions.OurHTMLcouldchangetosomethinglikethis;let’scallourvariationofthe.calendar-component__list.calendar-component__list--smallersincethevariationisdefiningasmallerwidth:1<divclass="calendar-component">

2<ulclass="calendar-component__listcalendar-component__list--smaller">

3<liclass="calendar-component__list-item">Jan<spanclass="calendar-componen\

4t__day">01</span></li>

5<liclass="calendar-component__list-item">Feb<spanclass="calendar-componen\

Page 45: Front-End Fundamentals: A practical guide to front-end web development

6t__day">29</span></li>

7</ul>

8<ulclass="calendar-component__list">

9<liclass="calendar-component__list-item">NewYear's!</li>

10<liclass="calendar-component__list-item">LeapDay!</li>

11</ul>

12</div>

Now,ifweswap.calendar-component__list:first-childwithournewmodifierclass.calendar-component__list--smallerwe’llbeinbusiness!

Sowhywouldyouwanttodoallthis?Well,thereareprobablyalotofopinionsoutthereregardingwhatmakesthissouseful,butafewofthemoreimmediatelydigestiblereasonsare:

1. BEMmakesscanningCSSdocumentseasier2. BEMavoidsdeepselectorandinheritancehell3. BEMmakesitsimpletolookatavisualelementandfigureoutexactlywhichCSS

selectorisstylingit

AninterestingthingaboutwritingyourCSSentirelywithBEMisthatyou’reessentiallyremovingtheCfromCSSandignoringthecascadingfeature.Thismeansyouendupwritingalotmoreclasses,butyoualsoavoidsomeofthetroublethatthecascadecancause.

IfyouwanttoreadmoreaboutBEMthanthisshortintroductioncanprovide,checkouttheofficialwebsite.

UtilityAutilitybasedmethodologycentersaroundtheideathatasingleclassshoulddoveryfewthingsandthatanynumberofCSSclassescanbeappliedtoanelementtoobtainthedesiredoutput.Usingautilityclassparadigmisactuallyfairlystraightforward,althoughorganizationcanbecomequiteahassleduetothesheernumberofutilityclassesthatgetcraftedthroughoutthecourseofasitebuild.

Beforewetalkaboutwhythismightbeuseful,let’stakealookatsomeutilityclassexamples:1.small-text{

2font-size:11px;

3}

4

5.underlined{

6text-decoration:underline;

7}

8

9.black-bg{

10background-color:#000000;

11}

12

13.float-left{

14float:left;

15}

Page 46: Front-End Fundamentals: A practical guide to front-end web development

Theseareallfairlystandardexamplesofutilityclasses.Eachclasspresentedabovedoesonlyonething,althoughitisperfectlyacceptableforthemtodomore,soifyouwantedsomeparagraphoftexttobe11pxandunderlined,you’dneedtoapplyboth.small-textand.underlinedtothemarkup:1<pclass="small-textunderlined">Loremipsum</p>

Ifthissoundsinsane,nobodycanblameyou.Theusefulnessofthismethodologyistoughtoseeatfirst,solet’stalkaboutwhywe’dgothisroute.

Firstly,it’sveryquicktostylesomethingnewifyou’vegotanarmyofutilityclassesalreadysetupinyourstylesheet.Ifyouneedyourtexttobered,byGod,justthrowa.red-textclassonit.

Secondly,usingutilityclassesmeansthereisverylittlerepetitioninyourstylesheetswhichmeansasmalleroverallfilesizewhich,inturn,meansafasterloadtimeforyourstylesheet.Withacomponentbasedmethodologyyoumayfindyourselfrepeatingfloat:left;onlotsofelements,butusingutilityclassesyoumayonlyhaveonefloat:left;inyourentiredocument.

Usingutilityclassesexclusivelybringsitsownsetofchallengestoaprojecthowever,asitbecomestheresponsibilityofHTMLauthorstostyletheircontentaswellascreateit.Thebenefitsofeaseandreducedrepetitioninyourstylesheetsmightbenegligiblewhencomparedwiththetroubleofcreatingnewcontentusingutilityclasses.IfyourworkflowmakesiteasiertomodifyHTMLclassesthanupdatestylesheets,utilityclassesmightbeforyou.

MixingandMatchingProbablythemostusefulwaytoauthoryourstylesistotakeabitfrombothcomponentandutilitymethodologies.

Buildingyourvisualpatternsascomponentsisoneofthebestwaystomakesureyourstylesscalewell.Ittakesalotofthoughtoutoftheauthoringprocessbyprovidingwhatare,essentially,templatesofstyle.Bycreatingone-offutilityclassesthatdon’treallyneedtobeembeddedintoaparticularcomponent,youcaneasesomeofthepainofmodifyingacomponentasneeded.

Let’sjumpbacktoourcalendarcomponentexampleandintroduceanewscenariothatmixesthetwomethodologies.

Let’ssaythatonoursitewehavemultipleinstancesofourcalendarcomponentsprinkledinvariousareasofthelayout.Oneinasidebar,oneinthemastheadandanotherinthefooter(weREALLYwantpeopletoknowaboutourupcomingeventsokay?).However,whenauservisitsoursiteonabrowserlessthan400pxwidewewanttohidethecomponentinthefooterwithoutactuallyaffectingtheotherinstancesonthepage.Thisistheperfectspotforautilityclassbecausewehaveascenarioinmindthatcouldbeappliedtoanycomponent.Thatscenariois“hidethisthingwhenthesitewidthislessthan400px.”

Ourutilityclassmightlooklikethis:

Page 47: Front-End Fundamentals: A practical guide to front-end web development

1.hide-under-400{

2display:none;

3}

4@mediaonlyscreenand(min-width:400px){

5.hide-under-400{

6display:block;

7}

8}

Nowwecanapply.hide-under-400toourcomponent,oranyothercomponent,andhaveitdisappearfromviewwheneverourbrowserwindowislessthan400pxwide.

PreprocessorsApreprocessorisaprogramthattakessomekindofinputandspitsoutanotherkind.Intheworldoffront-enddevelopment,wehaveanumberoftheseprogramsatourdisposalwhichmakeswritingCSS(orJavaScriptandHTML)amorepleasantexperience.ThebasicideaisthatpreprocessorsletyouwriteyourstylesusingadifferentsyntaxwhichthenspitsoutintoplainoldCSSwhichyourbrowsercanread.

ThemainbenefitofusingpreprocessorsisthatmostcomewithfeaturesnotnormallyfoundinCSS(atthetimeofwriting,anyway).Thefeaturesthemselvesarealittledifferentdependingonwhichpreprocessorwe’relookingat,butmostcomewithawaytowritevariablesforstoringvaluesandnestingsupportso,amongotherthings,youdon’tneedtowritelengthyselectors.

Sass(SyntacticallyAwesomeStyleSheets)Atthemoment,theSasslanguageiswidelyusedinthefront-endcommunity.Sasssportsanumberoffantasticfeaturesandhastwosyntaxestochoosefrom;theoriginalindentedsyntaxSassandthemorerecentSCSSsyntaxwhichusethe.sassand.scssfileextensionsrespectively.TheoriginalversionofSassisbuiltonRubyalthoughotheroptionsareavailableincludingPHP,C,andJava.SassevenhasascriptinglanguagecalledSassScriptunderthehoodsoifyou’recomfortablewithsuchthings,youcouldevenwriteyourownfeatures.

Installing

TogetstartedusingSass,you’llneedtoinstalltheprogramonyourcomputeroruseathird-partyapplicationthatcontainsitsuchasCodeKitorScout.Inthissectionwe’llcoverthetypicalwaytoinstallitwithRuby,butforamorethoroughoverviewofalltheoptionsoutthere,visitSass’installationpage.

ThissectionalsoassumesthatyouhaveRubyalreadyinstalledonyourmachine.InstallingRubyisoutsidethescopeofthisbook,butifyou’reusingaMacthegoodnewsisthatyou’vealreadygotit.WindowsandLinuxmachineshavetheirowninstallationprocesses.

Onceyou’vegotRubyonyoursystem,simplyheadtoyourcommandprompt(TerminalinOSX,cmdinWindows)andinstalltheSassgem:1geminstallsass

Page 48: Front-End Fundamentals: A practical guide to front-end web development

That’sallthereistoit!Youcanmakesureeverythingisinstalledproperlybyrunningsass-v.Ifyougetoutputlikeso,thenyou’reallset:1sass-v

2Sass3.4.9(SelectiveSteve)

UsingSass

Nowthatyou’vegotSassinstalled,you’llfindit’sfairlysimpletouse.ThepatternforusingSassfromthecommandlineiseasy:1sass[options][input][output]

Soifyou’vegotastyle.sassfileinyourcurrentdirectoryyoucouldrun:1sassstyle.sassstyle.css

tohaveSasscompileyourstyle.sassstylesheetintostyle.css.

UsingtheSCSSsyntaxisalittletrickier,andyou’llneedtopassanoptiontothecommandtotellitthatyou’reusingSCSSinsteadofSass.Assumingyouhavestyle.scssinsteadofstyle.sass,thatcommandwouldlooklikethis:1sass--scssstyle.scssstyle.css

Youcanwatchafileoranentiredirectoryforchangestoyour.sassfilesandhavetheprogramautomaticallycompileCSSanytimeitdetectschangesusingthe--watchoption.Thisisreallyquitehandyifyou’reworkingonaprojectanddon’twanttokeeprunningthecommandmanuallytoseethechangesyou’remaking.

Towatchasinglefile:1sass--scss--watchstyle.scss:style.css

Towatchanentiredirectory:1sass--scss--watchyour_scss_directory:your_compiled_css_directory

ThesasscommandhasanumberofotherusefuloptionsavailabletocustomizetheoutputofyourcompiledCSS.Youcanseethefulllistbyrunning:1sass-h

TheSassSyntax

TheoriginalSasssyntaxisnotdirectlycompatiblewithCSS.Thatmeansyoucan’tjustchangeyourfileextensionsto.sassandexpectthingstorun.Sassusesindentationtoseparatepropertydeclarationsfromselectors,andnewlinesinsteadofsemicolonstodenotetheterminationofaproperty.Asaquickexample,let’scomparethesamestyledeclarationinCSSandSass:

CSS1.class-name{

2color:purple;

3background:blue;

4}

Sass1.class-name

2color:purple

Page 49: Front-End Fundamentals: A practical guide to front-end web development

3background:blue

Thiscanbealittleconfusingtoactuallyuseatfirst,butifyou’restartinganewprojectyoumayfinditpreferabletousetheSasssyntaxbecauseyouactuallyendupwritingfeweroverallcharacters.

TheSCSSsyntax

UnliketheSasssyntax,theSCSSsyntaxiscompatiblewithCSS.YoucancopyandpasteanygenericCSSintoa.scssfileandhaveabsolutelynoissues,althoughofcourseitdoesn’tworktheotherwayaround.TheSCSSsyntax,forthemostpart,usestheexactsamesyntaxthatCSSdoes.Yougroupsetsofpropertiesonaselectorwithbracesandyouterminatepropertydeclarationswithasemicolon.Indentiondoesn’tmatteratall,althoughyoushouldbeconsistentforyourownmentalwellbeing.

ManypeopleprefertheSCSSsyntaxbecauseit’ssocompatiblewithexistingCSS.Ifyou’vealreadygotawellestablishedprojectandyou’dliketostartswitchingtoSass,usingtheSCSSsyntaxisaneasywaytogetstarted.

VariablesinSass

VariablesinSassaredenotedbya$whichshouldfeelprettyfamiliarifyou’veeverusedalanguagelikePHP.BoththeSCSSandSasssyntaxesusethesameformatfordeclaringavariable,althoughintheSasssyntaxyouwon’tneedtouseasemicolonattheend:

Sasssyntax1$my-blue-variable:#0000ff

2headerh2

3color:$my-blue-variable

SCSSsyntax1$my-blue-variable:#0000ff;

2headerh2{

3color:$my-blue-variable;

4}

CSSoutput1headerh2{

2color:#0000ff;

3}

NestingSelectorsinSass

Sasshastheconceptofnestingselectorswithinoneanothertoavoidhavingtowritereallylongstringsofselectorstogetthespecificityyouwant.Theeasiestwaytounderstandthisconceptistovisualizeit.Let’ssaywewanttotargetthisspecificCSSselector:#mainarticle.author.Todothatwecanwriteourstylesfor.authorinsidethestylesforarticleandwritethoseinside#main.TodothatwithSass,we’dwrite:

Sasssyntax1#main

2background:#ffffff

3

4article

5margin:0auto

Page 50: Front-End Fundamentals: A practical guide to front-end web development

6color:#000000

7

8.author

9background:#cecece

10padding:10px

SCSSsyntax1#main{

2background#ffffff;

3

4article{

5margin:0auto;

6color:#000000;

7

8.author{

9background:#cecece;

10padding:10px;

11}

12

13}

14

15}

CSSOutput1#main{

2background:#ffffff;

3}

4#mainarticle{

5margin:0auto;

6color:#000000;

7}

8#mainarticle.author{

9background:#cecece;

10padding:10px;

11}

Selectingparentswith&

AnotherhandyfeatureofnestingthatSassprovidesisawaytoreferencetheparentselectorusing&.Thisisparticularlyhandywhenyouwantanestedselectortohaveadifferentstylewhenitsparentisslightlydifferent,forinstance,whentheparenthasanextraclassorstate.Aneasyexampleofthisparentselectorusageisstylingthevariousstatesofalink:

Sasssyntax1a

2color:blue

3

4&:hover

5color:green

6

7.some-class&

8color:purple

SCSSsyntax1a{

2color:blue;

Page 51: Front-End Fundamentals: A practical guide to front-end web development

3

4&:hover{

5color:green;

6}

7

8.some-class&{

9color:purple;

10}

11

12}

CSSOutput1a{

2color:blue;

3}

4a:hover{

5color:green;

6}

7.some-classa{

8color:purple;

9}

Anotherinterestingfeatureofthe&selectorisitsabilitytocreatecombinatorialexplosionsofselectorsusing&+&withinanestedlistofselectors.Thiswillgenerateeverypossiblepermutationoftheparentselectors.

Note:The+operatorinCSSdenotessiblingelements.

Sasssyntax1ul,quote,p

2

3&+&

4margin:0

SCSSsyntax1ul,quote,p{

2

3&+&{

4margin:0;

5}

6

7}

CSSOutput1ul+ul,

2quote+ul,

3p+ul,

4ul+quote,

5quote+quote,

6p+quote,

7ul+p,

8quote+p,

9p+p{

10margin:0;

11}

MixinsinSass

Page 52: Front-End Fundamentals: A practical guide to front-end web development

Mixinsareareallyhandywaytogroupsetsofpropertiestogethersoyoucanreusethem.Acommonpracticeistousemixinsforwritingvendorprefixes(e.g.-webkit-border-radius,-moz-border-radiusetc),butyoucanusethemtogroupanykindofpropertiesyouwant.

Todefineamixin,declare@mixinyour_mixin_nameinSCSSand=your_mixin_nameintheSasssyntax.Let’screateamixinthataddsadashedborderandsomepaddingaroundanelement:

Sasssyntax1=dashed_border

2border:1pxdashed#000000

3padding:10px

SCSSsyntax1@mixindashed_border{

2border:1pxdashed#000000;

3padding:10px;

4}

Nowthatthemixinisdefined,wecanuseitonanyselectorwewantbyusingthemixin’sname,prefixedwith+inSassand@includeinSCSS:

Sasssyntax1.foo

2+dashed_border

SCSSsyntax1.foo{

2@includedashed_border;

3}

CSSOutput1.foo{

2border:1pxdashed#000000;

3padding:10px;

4}

Mixinscanalsotakearguments!Let’ssaywewanttogivetheoptiontochangethebordercolorandtheamountofpaddingwhereverweusethemixin.Todothat,we’llneedtochangeourmixindefinitionsalittlebit:

Sasssyntax1=dashed_border($border_color,$padding)

2border:1pxdashed$border_color

3padding:$padding

SCSSsyntax1@mixindashed_border($border_color,$padding){

2border:1pxdashed$border_color;

3padding:$padding;

4}

Page 53: Front-End Fundamentals: A practical guide to front-end web development

Nowwewouldsimplypassinacolorasthefirstparameterandapaddingvalueasthesecond:

Sasssyntax1.foo

2+dashed_border(#dddddd,4px)

SCSSsyntax1.foo{

2@includedashed_border(#efefef,.5em);

3}

Additionally,mixinsmaybedefinedwithdefaultargumentvalues.Adefaultvalueforanargumentwillbeusedwhennoargumentispassedwhenthemixinisreferencedinaselector.Let’sreuseourdashedbordermixinandthistimedefineadefaultvalueforthe$border_colorargument.Todothis,we’llneedtochangetheorderofourargumentsinourmixin’sdefinitionbecauseargumentswithdefaultvaluesmustcomeafterargumentswithout:

Sasssyntax1=dashed_border($padding,$border_color:#000000)

2border:1pxdashed$border_color

3padding:$padding

SCSSsyntax1@mixindashed_border($padding,$border_color:#000000){

2border:1pxdashed$border_color;

3padding:$padding;

4}

5

6.foo{

7//Withoutasecondargument,thedefaultbordercolorwillbeused.

8@includedashed_border(10px);

9}

10

11.bar{

12@includedashed_border(10px,green);

13}

CSSOutput1.foo{

2border:1pxdashed#000000;

3padding:10px;

4}

5

6.bar{

7border:1pxdashedgreen;

8padding:10px;

9}

Sassmixinscanalsobecalledbyusingargumentkeywordslikeso:@includedashed_border($padding:10px,$border_color:green);.Toillustratetheusefulnessofthisfeature,let’saddathirdargumenttodashed_bordercalled$border_widthandgiveitadefaultvalue:

Page 54: Front-End Fundamentals: A practical guide to front-end web development

Sasssyntax1=dashed_border($padding,$border_color:#000000,$border_width:1px)

2border:$border_widthdashed$border_color

3padding:$padding

SCSSsyntax1@mixindashed_border($padding,$border_color:#000000,$border_width:1px){

2border:$border_widthdashed$border_color;

3padding:$padding;

4}

Nowsupposethatinourselector.foo,wewanttoaddadashedborderwithawidthof5pxbutleavethedefault$border_colorvaluealone.Since$border_widthisthethirdargument,wecannotsimplypassavaluetoitwithoutalsopassingavalueto$border_colorunlessweusethekeywordfunctionality:

Sasssyntax1.foo

2+dashed_border(10px,$border_width:5px)

SCSSsyntax1.foo{

2@includedashed_border(10px,$border_width:5px);

3}

CSSOutput1.foo{

2border:5pxdashed#000000;

3}

Usinganargument’skeywordinthereferencetothemixin,youcansetthatargument’svaluenomatterwhatpositionit’sdefinedin.@includedashed_border($border_color:green,$padding:4px,$border_width:8px)wouldcompilejustfinesincewe’reusingkeywords,eventhoughwe’redeclaringargumentvaluesinadifferentorderthantheyweredefinedinthemixin.

Sassmixinsareverypowerfulandthere’salotmoreyoucanaccomplishwiththemthanwhat’sbeenshownhere.ForacompleteoverviewofmixinsinSass,takealookatthemixindocumentation.Hereyou’llfindalotmoreinformationaboutmixinarguments,likehowtousevariablesasarguments,howtopasscontentblockstoamixin,andvariablescopewithinmixinsamongotherhandynuggetsofinformation.

ControlExpressions

Toaddtothepotentialcomplexityofthelanguage,Sasssupportstheusageofcontrolexpressionssuchasif,for,each,andwhile.Formoreinformationonthissubject,takealookatSass’documentation.Controlexpressionsarenotlimitedtousageinmixins,butthisisthemostcommonplaceyou’llfindtheminthewild.

Extending

Theconceptof‘extending’aselectorinSassissomewhatsimilartomixins.Youcantakeallofthepropertiesappliedtooneselectorandextendthemontoanotherone.

Page 55: Front-End Fundamentals: A practical guide to front-end web development

TheactualusageoftheextendfunctionalityisthesameinbothSasssyntaxandSCSS.Simplywrite@extendbeforethenameoftheselectoryouwanttoextendinthepropertylistofyourselector:

Sasssyntax1.div_1

2color:blue

3

4.div_2

[email protected]_1

SCSSsyntax1.div_1{

2color:blue;

3}

4

5.div_2{

[email protected]_1;

7}

Themaindifferencebetweenextendingaselectorandusingamixinisthatifyouuseamixinmultipletimesonamultitudeofdifferentselectors,yourCSSoutputwillhavethesamecontentrepeatedmultipletimes.Usingourmixinexamplefromabove,thatmightlooklike:

Sasssyntax1.div_1

2+dashed_border

3

4.div_2

5+dashed_border

SCSSsyntax1.div_1{

2@includedashed_border();

3}

4

5.div_2{

6@includedashed_border();

7}

CSSOutput1.div_1{

2border:1pxdashed#000000;

3padding:10px;

4}

5

6.div_2{

7border:1pxdashed#000000;

8padding:10px;

9}

Byextendingaselectorontoanotherone,thetwoselectorswillbecombinedandonlythedifferenceswillbesplitoutintotheirownselectors:

Sasssyntax

Page 56: Front-End Fundamentals: A practical guide to front-end web development

1.div_1

2border:1pxdashed#000000

3padding:10px

4

5.div_2

6color:blue

[email protected]_1

SCSSsyntax1.div_1{

2border:1pxdashed#000000;

3padding:10px;

4}

5

6.div_2{

7color:blue;

[email protected]_1;

9}

CSSOutput1.div_1,.div_2{

2border:1pxdashed#000000;

3padding:10px;

4}

5

6.div_2{

7color:blue;

8}

Operators

TheSasslanguagealsosupportssomemathematicaloperatorsthatyoucanusewhenwritingyourstyles.Thesupportednumberoperatorsare:

+-Addition--Subtraction*-Multiplication/-Division%-Modulo

Inadditiontothesemathematicaloperators,Sassincludesrelationalandequalityoperators,typicallyforuseincontrolexpressions:

<-Lessthan>-Greaterthan<=-Lessthanorequalto>=-Greaterthanorequalto==-Equalto!=-Notequalto

PartialsandImporting

AcommonwaytoorganizeyourCSSistosplitoutcategoriesorspecificchunksofstylesintotheirownfiles.Usingacomponentbasedmethodology,eachindividualcomponent

Page 57: Front-End Fundamentals: A practical guide to front-end web development

mighthaveitsownfilesothatdevelopersknowexactlywheretofindaparticularcomponent’sstyles.

OutoftheboxCSSsupportsthe@importdirectivewhichisusedforincludingotherCSSfilesintoaCSSfile.Thisisgreatfororganization,butnotsogreatfortheoverallperformanceofyourpage.Eachusageof@importcreatesanHTTPrequestwhichwillslowdowntherenderingofyourpage.

WithSass,youcancreate‘partials’whichareessentiallythesameassiloedCSSfilesandtheycanbeincludedinanotherSassfileinthesamewaythatCSScan@importotherCSSfiles.Thedifferenceis,whenSasscomesacrossan@importdirectiveduringcompiletime,itconcatenatesthefilestogethercreatingasingleCSSstylesheet.Inthisway,youcanhavealltheniceseparationofstyleswithoutcreatingexcessHTTPrequests.

Here’sanexampleofhowtouseapartialfilewithinSass:

Sasssyntax1/*main.sass*/

2@importpartial

3

4.main_class

5background:#efefef

6

7/*_partial.sass*/

8.partial_class

9color:purple

SCSSsyntax1/*main.scss*/

2@import'partial';

3

4.main_class{

5background:#efefef;

6}

7

8/*_partial.scss*/

9.partial_class{

10color:purple;

11}

CSSOutput1/*main.css*/

2.partial_class{

3color:purple;

4}

5.main_class{

6background:#efefef;

7}

Thenamewegavethepartialfileinthisexample,_partial.sassisprefixedwithanunderscoresothatSassdoesn’tcreateapartial.cssfilewhenwecompilethedirectory,whichitwilldoifweleaveofftheunderscore.Thereisnorequirementthatpartialfilesbenamedthiswayandimportingapartialusingthenameofthefilewithouttheextensionwillworkwhetherornotyou’veprefixedthefilenamewithanunderscore.

Page 58: Front-End Fundamentals: A practical guide to front-end web development

Itisalsoimportanttonotethatthecontentsofourpartialwillappearinthefinaloutputintheplacetheywereimportedwithinthemainfile.Inourexampleabove,[email protected]_class,sothecontentsofourpartial,.partial_classwerecompiledoutabove.main_class.

OtherSassTools

ThepopularityofSasshasgivenrisetoanumberofauthoringframeworksandlibrariesbuiltspecificallyforthelanguage.ThelargestplayersinthisspaceatthetimeofwritingareprobablyCompassandBourbon.Eachoftheseprovidesagoodnumberofbuilt-inmixinsandfunctionalitythatyoumightotherwisecreatebyhandforyourprojects,includinglayouthelpers,typographyutilitiesandCSS3shortcuts.

Thebenefitsofusinglibrarieslikethesearemany,butdependingonthescopeandsizeofyourprojecttheycouldverywellbeoverkill.TyingyourSassprojecttoasingleframeworkorlibrarysuchasthesecanbealimitingfactorwhenSassitselfgetsupdatedandyouwanttoupdatetothelatestversionsinceyourlibrarywilllikelyrequireaspecificversionofSasstorun.

Overall,toolslikeCompassareincrediblyuseful,particularlyforbeginners.

Summary

Inthisbook,we’reonlyscratchingthesurfaceofwhatSassiscapableof.ThereareotherpowerfulfeaturesinthislanguagethatarehonestlybestdescribedwithinSass’owndocumentationandgivingsuchacursoryoverviewashasbeengiventherestofthefeaturespresentedinthisbookwouldlikelybeadisservicetoreaders.Moredetailedinformationonfeatureswe’vecoveredaswellasthosewehaven’tcoveredsuchaslists,maps,placeholderclasses,anddefiningcustomSassfunctionsamongotherscanbefoundhere.

LessLess.jsisaJavaScriptbasedpreprocessorthatatonepointwaskingoftheveritableCSSpreprocessorhill.Morerecently,itseemstohavetakensomewhatofabackseattoSassinoverallpopularity,butitisstillwidelyused.LessandSasshaveaverysimilarfeatureset.

LikeSass,LessisaverypowerfullanguageandjustliketheSCSSsyntaxosSass,Less’syntaxisbackwardscompatiblewithvanillaCSSmakingitrelativelyeasytopickupanduse.

Lesscanbeusedviathecommandline,programmaticallyviaJavaScriptorontheflyviathebrowserbyincludingtheless.jsscriptonyourpage.ThelattermethodisnotrecommendedduetothesheersizeofthescriptandthefactthatsomebrowsersmaycompileLessintoreadableCSSmoreslowlythanothers.Inthisbook,we’llconcernourselvesonlywiththecommandlineusage.

Installation

ToinstallLesslocallyforuseonthecommandline(thepreferredmethod),you’llneedtohavethenpmpackagemanagerinstalled.TheinstallationprocessfornpmcanbefoundintheDependencyManagementchapterofthisbook.

Page 59: Front-End Fundamentals: A practical guide to front-end web development

Onceyouhavenpm,installationisabreeze.Simplyheadtoyourcommandlineandrun:1npminstall-gless

Many*nixsystemsalreadycomewithaprogramcalledless,sowhatourpackagemanagerisactuallyinstallinghereisaprogramcalledlesscwhichstandsfor“lesscompiler.”Tocheckwhetherornottheinstallationwassuccessful,runthefollowingandlookforsimilaroutput:1lessc--version

2lessc2.1.2(LessCompiler)[JavaScript]

UsingLess

TohaveLesscompileourcodewecansimplyrunthelesscprogramonourLessfile(theextensionforLessfilesis.less):1lesscstyle.less

Thiswillprintoutthecompiledresulttoyourterminalscreenasapreview.Ifyouactuallywanttosaveyourcompiledstylesyou’llneedtosendthatoutputintoitsownfile:1lesscstyle.less>style.css

ThelesscprogramhasatonofoptionsyoucanusetotweaktheoutputofyourcompiledLess.Toseethem,run:1lessc--help

VariablesinLess

VariablesinLessaredefinedbyprefixingavariablenamewith@:

Less1@a-less-variable:10px;

2

3.foo{

4width:@a-less-variable;

5}

CSSOutput1.foo{

2width:10px;

3}

Lessvariablesdonotneedtobedefinedbeforetheyareusedinadocument.Intheaboveexample,@a-less-variablecouldhavebeendefinedbelow.foowithoutanyissue.

Aninteresting,althoughmaybenottotallyintendedfeatureofLess’variables,isthattheyarescoped,meaningthatthecompilerwillsearchforavariabledefinitionwithinthelocalscopeofaselectorbeforemovinguptoitsparent.Inthecaseofnestedselectors,thismeansmovinguptotheparentselector.Inthecaseofselectorswithnoparent,Lesswilllookintheglobalscope.

Here’sanexample:1@dark-color:#000000;

2

3.foo{

Page 60: Front-End Fundamentals: A practical guide to front-end web development

4@dark-color:#777777;

5color:@dark-color;

6}

Above,[email protected]:@dark-coloritfirstlookedwithinthatselectorforadefinitionof@dark-colorandonfindingone,appliedittothepropertythatreferencedit.Therefore,thecolorusedis#777777.

If@dark-colorhadnotbeendefinedinthislocalscope,thecompilerwouldhavemovedupalevel,totheglobalscopetosearchforadefinitionof@dark-color.

ThisconceptofvariablescopeisveryimportanttogetahandleonwhenusingLesssincethecompilerwillusethelastdefinitionofavariableinthecurrentscope.

Inthefollowingexample,we’lldefine@dark-coloranumberoftimesandseewhathappenstotheoutput:1@dark-color:#000000;

2

3.foo{

4color:@dark-color;

5}

6

7@dark-color:#777777;

8

9.bar{

10color:@dark-color;

11}

12

13@dark-color:#333333;

Intheaboveexample,both.fooand.barwillbeoutputwithacolorof#333333sincethatwasthelastdeclarationof@dark-colorinthecurrentscope.NotethatthisisnotsomethingonewouldactuallywriteandissimplybeingusedtoillustratethefactthattheLessreadsvariablesbottom-to-topinthecurrentscope.

VariablesinLessareconstantsandgenerallyshouldnotbedefinedmorethanonce.

NestingSelectorsinLess

NestinginLessfunctionsthesamewayasnestingusingSass’SCSSsyntax,includingtheusageof&asaparentselector:

Less1.foo{

2color:green;

3

4.bar&{

5color:black;

6}

7

8.baz{

9color:purple;

10}

11

12}

CSSOutput

Page 61: Front-End Fundamentals: A practical guide to front-end web development

1.foo{

2color:green;

3}

4

5.bar.foo{

6color:black;

7}

8

9.foo.baz{

10color:purple;

11}

Mixins

MixinsinLessarealittledifferentthanmixinsinSass.Infact,they’reabitclosertothewaySass’extendfunctionalityworks.InLess,mixinsareessentiallyclassorIDselectorsthemselveswhichcanbeextendedontootherclasses.TomixinanIDorclass’propertiesinadifferentselector,simplywritethemixinselector’snameoptionallysuffixedwith()iftherearenoarguments:

Less1.mixin{

2border:1pxsolid#000000;

3}

4

5.foo{

6.mixin();

7}

CSSOutput1.mixin{

2border:1pxsolid#000000;

3}

4

5.foo{

6border:1pxsolid#000000;

7}

Ifyouwanttodefineamixinwithoutitgettingcompiledasitsownselector,suffix()onthedefinitionofthemixinlikeso:

Less1.mixin(){

2color:black;

3}

4

5.foo{

6.mixin;

7}

CSSOutput1.foo{

2color:black;

3}

Page 62: Front-End Fundamentals: A practical guide to front-end web development

Thisalsoworkswithmoredeeplyspecifiedmixinselectors.Duetothisbehavior,itispossibletonamespaceyourmixinswhichishandyforcategorizingmixinsthatallrelatetosomesimilarproperty.AsimplisticexampleofthiswouldbetonamespaceasetofmixinsthatcontrolthedirectionofCSS’floatproperty.The.floatclassiscreatedasthemixinwhichwedon’twanttobeoutputtedinourcompiledCSSandnestedwithinare.leftand.right.In.fooand.barwecallthenamespacedmixins:

Less1.float(){

2

3.left{

4float:left;

5}

6

7.right{

8float:right;

9}

10

11}

12

13.foo{

14.float.left();

15}

16

17.bar{

18.float.right();

19}

CSSOutput1.foo{

2float:left;

3}

4

5.bar{

6float:right;

7}

Thereareactuallyamultitudeofwaystousenamespacedmixinsinthislanguage.Forinstance,allofthefollowingwouldoutputthesameCSSwhenaddedtothepropertyblockofaselector:

.float.left

.float.left()

.float.left

.float.left()

.float>left

MixinArguments

MixinsinLessalsosupportoneormoreargumentsintheirdefinition.Argumentsdefinedontheseso-calledparametricmixinsareeithercommaseparatedorsemicolonseparatedandagain,justlikeSass,mixinargumentscanhavedefaultvaluesandcanbeaccessedusingtheargumentkeywordswheretheyarereferenced.BelowisasimpleexampleofaLessmixinwithmultiplearguments:

Page 63: Front-End Fundamentals: A practical guide to front-end web development

1.mixin-foo(@border-width,@border-style,@border-color:#000000){

2border:@border-width@border-style@border-color;

3}

Wecancallthismixinonanewselectorinanumberofways.Wecansimplypassvaluesinacommaseparatedlist,specifytheargumentvalueswithkeywords,andcompletelyignorethethirdparametersinceitwasdefinedwithadefaultvalueof#000000:

.mixin-foo(1px,solid,#0000ff)

.mixin-foo(@border-width:1px,solid,#0000ff)

.mixin-foo(1px,solid)

Commasinamixin’sargumentdefinitioncanserveanotherpurposebeyondactingasaseparator;theymayalsoactasaCSSlistseparator.Ifyoudecidetousecommastoseparatearguments,thenyouremovetheabilitytoaddCSSlistasanargumentsinceLesswillassumeeachiteminthelistisitsownargument.Forthisreason,itisrecommendedtoseparateargumentswithsemicolonsratherthancommas.

Let’srewrite.mixin-footoincludeaCSSlistargument:

Less1.mixin-foo(@border-width;@border-style;@border-color;@font-stack){

2border:@border-width@border-style@border-color;

3font-family:@font-stack;

4}

5

6.foo{

7.mixin-foo(1px;solid;#0000ff;Helvetica,Arial,sans-serif);

8}

CSSOutput1.foo{

2border:1pxsolid#0000ff;

3font-family:Helvetica,Arial,sans-serif;

4}

SomethingtonoteaboutLessmixinsisthatitiscompletelyvalidtowritemultiplemixinsofthesamenamewithavaryingnumberofargumentsoneach.Whenamixinlikethisisreferencedinaselector,Lesswillattempttouseanyandallmixinswhosenumberofpassedargumentsmatchthenumberofdefinedarguments.Toseethisfunctionalityinaction,let’sdefineacoupleversionsof.mixin-foo:

Less1//MixinA

2.mixin-foo(@border-width;@border-style;@border-color;@font-stack){

3border:@border-width@border-style@border-color;

4font-family:@font-stack;

5}

6

7//MixinB

8.mixin-foo(@line-height,@height:100px){

9line-height:@line-height;

10height:@height;

11}

Page 64: Front-End Fundamentals: A practical guide to front-end web development

12

13//MixinC

14.mixin-foo(@width){

15width:@width;

16}

17

18//MixinD

19.mixin-foo(@font-size){

20font-size:@font-size;

21}

22

23.foo{

24.mixin-foo(100px);

25}

CSSOutput1.foo{

2line-height:100px;

3height:100px;

4width:100px;

5font-size:100px;

6}

Sowhathappenedthere?Ourcallto.mixin-fooincludedonlyoneparameterwhichmatchedthenumberofargumentsdefinedforbothMixinCandMixinDso.foogotitswidthandfont-sizepropertiesfromthosetwomixinsrespectively.Additionally,MixinB’ssecondargumenthadadefaultvaluedefinedsoourcallof.mixin-foo(100px)in.foomatcheditaswell,givingitbothline-heightandheightvalues.

Intheabovescenario,ifwehadcalled.mixin-foowithfourarguments,onlyMixinAwouldhavematched.Ifwehadcalleditwithonlythreearguments,noneofthemixinswouldhavematchedandLesswouldhavegivenusanerrorduringcompiletime.

There’salotmoreyoucandowithLessmixinsthanwehaveroomtocoverinthescopeofthisbook.Tolearnmoreaboutusingmixinsasfunctions,argumentpatternmatching,andotherniftymixinfeaturesofLesscheckoutthedocumentation.

Extending

ExtendingaselectorontoanotherselectorispossiblebyusingLess’special:extendpseudo-class.Thispseudo-classtakesoneormoreargumentsofselectors.TheseargumentstellLesswhichselector’sstylesyouwanttoextendontothecurrentselector.Inalistofselectors,anyandallofthemmayusethe:extendpseudo-class:

Less1.foo{

2color:green;

3}

4

5.bar{

6background:black;

7}

8

9.baz:extend(.foo),

10.qux:extend(.bar){

Page 65: Front-End Fundamentals: A practical guide to front-end web development

11font-size:1.5em;

12}

CSSOutput1.foo,

2.baz{

3color:green;

4}

5

6.bar,

7.qux{

8background:black;

9}

10

11.baz,

12.qux{

13font-size:1.5em;

14}

Inadditiontotheselectorargument(s),the:extendpseudo-classmayoptionallybepassedthekeywordallwhichwillmatcheveryinstanceoftheprecedingselectorargument(s).Topiggy-backonourpreviousextendexample,let’screateanestedinstanceof.barandpass.qux:extend(.bar)theallkeyword:

Less1.foo{

2color:green;

3}

4

5.bar{

6background:black;

7

8.norf&{

9border-radius:8px;

10}

11

12}

13

14.baz:extend(.foo),

15.qux:extend(.barall){

16font-size:1.5em;

17}

CSSOutput1.foo,

2.baz{

3color:green;

4}

5

6.bar,

7.qux{

8background:black;

9}

10

11.norf.baz,

12.norf.qux{

13border-radius:8px;

Page 66: Front-End Fundamentals: A practical guide to front-end web development

14}

15

16.baz,

17.qux{

18font-size:1.5em;

19}

Above,wecanseethat.norf.bazand.norf.quxnowhavetheborder-radiuspropertyintheirruleset.Withouttheallkeyword,the.quxwouldhaveonlyextendedtheselectorwegaveit,.bar.Inthatscenario,.norf.barwouldnothavematchedourselectorargument.Selectorargumentswithouttheallkeywordmustmatchexactly.TheScopeof:extend

Intheresponsivedrivenworldoffront-enddevelopmentwelivein,you’llprobablyfindyourselfwritingalotofmediaqueriestochangethestyleofyourcontenttobestsuitavarietyofscenarios.Somethingtokeepinmindwhenusing:extendinLessisthatyoucannotextendaclassthatisoutsideyourcurrent@mediablock:

Less1@mediascreenand(min-width:400px){

2.foo{

3color:blue;

4}

5}

6

7@mediascreenand(min-width:600px){

8.bar:extend(.foo){

9background:brown;

10}

11}

12

13.baz{

14line-height:1.5;

15}

CSSOutput1@mediascreenand(min-width:400px){

2.foo{

3color:blue;

4}

5}

6

7@mediascreenand(min-width:600px){

8.bar{

9background:brown;

10}

11}

12

13.baz{

14line-height:1.5;

15}

Intheaboveexample,.bar’sextensionof.fooiscompletelyignoredsince.foodoesnotexistinthescopeofthis@mediablock.

Page 67: Front-End Fundamentals: A practical guide to front-end web development

Whileextendingacross@mediablocksisano-go,weareabletoextendaselectorwithina@mediablockontoagloballyscopedselector.Inthepreviousexample,that’s.baz.Thecaveathereisthatextendinga@mediascopedselectorontoagloballyscopedselectorwillkeepthe@mediascopeonoutput.Essentially,anythingyouextendthatcomesfromaselectorwithina@mediablockwillonlybeextendedinthat@mediablock:

Less1.baz:extend(.foo){

2line-height:1.5;

3}

4

5@mediascreenand(min-width:400px){

6.foo{

7color:blue;

8}

9}

CSSOutput1.baz{

2line-height:1.5;

3}

4

5@mediascreenand(min-width:400px){

6.foo,

7.baz{

8color:blue;

9}

10}

Summary

We’vecoveredalotaboutLess’featuresinthissection,buttherearemanymanymore.InalotofwaysLessandSassarequitesimilar,butunderthehoodandinspecificimplementationsoftheirsharedfeaturestherearealotofsubtledifferences.Less,asalanguage,isverymatureandwelldocumentedandshouldsuitjustaboutanyprojectjustfine.It’seasytogetstartedwithandasyougetmorecomfortableusingitthemorecomplexfeaturesitprovidescanbeanenormousassettoyourfront-endworkflow.

Ifyou’reinterestedinmorethanaquickintroductiontoLess,headovertotheLesswebsiteanddigin.

StylusTheStyluspreprocessorrunsonnodeandboastsahugenumberofquality-of-lifetypefeatures.TheStylussyntaxmakesnearlyeverythingoptional,fromcolonseparatorsbetweenpropertiesandvaluestobracesaroundrulesets,evenmixinargumentparenthesis.

Stylusisrelativelynewonthesceneanditsharesafewsimilaritieswithotherpreprocessors.Forexample,StylussupportsanindentedsyntaxthatcloselymatchesSass’originalsyntax.Additionally,StylussupportsnestingselectorsintheexactsamewaythatLessandSassdo,nomatterwhichsyntaxyou’reusing.

Installation

InstallingStylusworksjustlikeinstallingLessoranyothernodepackage,byusingnpm:

Page 68: Front-End Fundamentals: A practical guide to front-end web development

1npminstall-gstylus

Runaquickchecktoseeifeverythingworkedandyou’rereadytogetstarted:1stylus--version

20.49.3

UsingStylus

Thestylusprogramisbyitselfjustaninterpreter.Runningitwithoutanyparameterswillbringyouintoawritingmodewhereyoucanwritestyluscode.Whenyouquittheprogram,it’llspitoutwhateverStylusyouwroteintoregularCSS.

IfyouwanttobeabletosaveyourStyluscode,you’llneedtostoreitinafileandthenrunthestylusprogramonthatfile,muchlikeyouwouldforSassorLess.ThetypicalextensionforStylusfilesis.styl,althoughlikemostotherthingsinStylus,thatextensionisoptional.

OnceyouhaveafiletostoreyourStyluscodein,youcansimplyrun:1stylusyour_file.styl

andthestylusprogramwillgenerateaCSSfilewithamatchingname.Inthiscase,that’syour_file.css.

Toseethefulllistofthestylusprogram’soptionsrun:1stylus--help

StylusSyntax

Asmentionedintheintroductoryparagraphofthissection,almosteverythinginStylusisoptional.What’smore,youcanmixandmatchdifferentsyntaxstylesinthesameStylusdocumentwithoutanyproblem.

Thisisbothexceedinglyneatandpotentiallydisastrous,particularlyforaprojectwithmultipledevelopersworkinginthecode.Itishighlyrecommended,ifyouchooseStylusforyourproject,thateveryoneagreeonaparticularsyntax.LikeLessandSass’SCSSsyntax,StylusdoessupporttheregularCSSsyntaxinadditiontoalltheothercraziness.

Let’stakesomeexampleCSSandwriteitinafewvalid,butdifferent,Stylussyntaxes:1.foo{

2color:blue

3background:black

4}

5

6.foo

7color:blue;

8background:black;

9

10.foo{

11colorblue

12backgroundblack

13}

EveryoneofthosedifferentsyntaxeswillprovidethesameCSSoutput:1.foo{

2color:blue;

Page 69: Front-End Fundamentals: A practical guide to front-end web development

3background:black;

4}

VariablesinStylus

Unliketheotherpreprocessorswe’vecoveredsofar,youdon’tneedtoprefixanyparticularsymboltodenoteavariableinStylus,althoughitdoesoptionallyletyouuse$ifthathelpsyousleepatnight:

Stylus1darkColor=#777777

2

3.foo

4color:darkColor

CSSOutput1.foo{

2color:#777777;

3}

MixinsinStylus

ThesyntaxforStylusmixinsisalittledifferentfromtheotherpreprocessors,butifyou’vebeenreadingthischapter,thefollowingexampleshouldbefairlyeasytograspataglance:

Stylus1dashed_border_mixin(padding,border_width=1px,border_color=#000000)

2border:border_widthdashedborder_color

3padding:padding

4

5.foo

6dashed_border_mixin(5px)

CSSOutput1.foo{

2border:1pxdashed#000;

3}

InStylus,argumentsareseparatedbycommas,defaultvaluesaresetwith=,andforthemostpart,mixinslookthesameasvariables.

Extending

Stylussharesit’sextendfunctionalitywithSassinbothsyntaxandbehavior:

Stylus1.foo

2color:green;

3

4.bar

[email protected]

6background:blue

CSSOutput1.foo,

2.bar{

3color:#008000;

Page 70: Front-End Fundamentals: A practical guide to front-end web development

4}

5

6.bar{

7background:blue;

8}

Summary

TheStyluslanguagecanmakeyourownpersonalpreferencesasyntacticreality.Youcanreallywriteyourstylesnearlyanywayyouplease.Thislanguagealsosportsaheftynumberoffeaturesthattheotherpreprocessorswe’vecovereddo.Althoughtheauthorshaven’tusedStylusexclusivelyinanyclientprojects,youmightfindsomeofitsflexibilityveryattractive.IfStylusissomethingyou’dliketotryforyourself,youcanfindmoreinformationontheStyluswebsite.

PerformanceandCSSWhenyou’retryingtoimproveyourpage’sperformanceyoulikelydon’tthinkofCSSasaprimaryconcern.Inthegrandschemeofthings,improvingyourCSS’performancewon’tprovideasmanyquickgainsasreducingthenumberofimagerequestsoroptimizingyourJavaScriptwill.Thatsaid,therearestillsomethingsyoucandotomakebrowsersrenderyourCSSmoreefficiently.

Likely,yourlargestCSSperformancegainswillcomefromoptimizinghowyourstylesgetloadedontothepage.InliningcriticalCSSwillavoidtheneedtofetchastylesheetentirely.CompressingandminifyingyourCSSwithsomethinglikecssminwilldecreasethefilesizeofyourstylesheetsandlowerthetimeittakesforthebrowsertodownloadandparsethatstylesheet.Optimizingthewayyourserveractuallyservesyourstylesheetswillprovideasimilargain,butcachingandserverconfigurationareoutsidethescopeofthissection.

CSSPaintingAnotherperformanceoptimizationcancomefromimprovingthetimeittakesforabrowsertoactuallypaintallofyourstylesontothescreen.Themorethingsyouhaveonthescreen,themoreworkyourbrowserhastodoto.Thisisaprettytrickytopicand,formostwebsites,gettingdownanddirtywithvisualpainttimesisprobablynotnecessary,butit’sgoodtoknowabouthowitallworks.

AsthebrowserbuildstheDOMtree,itconcurrentlystartsbuildinguparendertreewhichismadeupofallthevisualstuffthat’sgoingtobepaintedontothescreen.Thisishowthebrowserknowsinwhatordertoapplyyourstylesonthescreen.Eachvisualelementbecomesanodeontherendertreecontainingallofthestylesthatmakeitup.Thesestylescomefrominlinestyles,thestylesheetsappliedtothepageand,insomecases,localstylesheetsthatusershaveaddedtocustomizetheirbrowsingexperience.Browserenginesallhandlethisprocessalittledifferently,buttheconceptisprettymuchthesame.

Thebrowserwilltypicallystartatthetopofadocumentandevaluatethestyleofthefirstelementitsees,usuallybody,beforepaintingit.Atthispointthebrowserdoesn’tcareaboutanythingelseinthedocument.Onceitfinishespaintingbodytothescreen,it’llmoveontothenextelementandgothroughthesameprocessofevaluatingthestyleand

Page 71: Front-End Fundamentals: A practical guide to front-end web development

paintingittothescreen.Afterthischildelementhasbeenpainted,thebrowserthentriestofigureoutifitneedstorepainttheparentelement.Ifthechildelementchangedtheheightofitsparent,bodywillbereevaluatedandpaintedoncemore.

Thenodesoftherendertreeallgetcalculatedindividuallyforlayoutandstyleandthat’sthegistofhowCSSactuallygetsapplied.Theactualpaintingpartofthatprocessfollowsastrictorderdefinedbyanumberofconditions.Theseconditionsarethingslikewhetherornottheelementbeingstyledisarootelement,whethertheelementispositionedinlineorblock,orwhetherit’sachildofanotherelement.Thegeneralorderofpaintinglookslikethis:

backgroundcolorbackgroundimageborderanychildelements

backgroundcolorbackgroundimageborder

YoucanfindalotmoreinformationaboutthisintheCSSspecification.

Sowhatcanwedowiththisinformation?Nowthatwe’reawareofhowthebrowserputsallourstylesintopractice,wecanfocusontryingtolimittheamountofoverallpaintingourbrowsershavetodobyapplyingstylesfurtherupthecascade,removingunnecessaryelementsfromthepage,andtrackingdownstylesthattakealongtimetopaint.ChromeactuallyhasapaintprofilerintheTimelinesectionofitsDevToolsthatmakesitprettyeasytoseeeachpainteventandhowlongittooktohappen.Withthisinformationyoucanquicklyseethestylesthattakethelongesttimeforthebrowsertorender.Moreoftenthannot,thingslikeCSSshapesandgradientswillbeyourprimaryculprits.

Page 72: Front-End Fundamentals: A practical guide to front-end web development

CSSSelectorsTheselectorsyouwritetostyleyourelementsgetevaluatedfromrighttoleft.Themorespecificyourselectorsarethemoreworkthebrowserneedstodotofigureoutwhetherornotanelementonthepageneedstobestyled.IfwehadsomeCSSlikethis,thebrowserwouldgothroughourentiredocumentlookingfor<span>elements.Ateach<span>itwouldlooktoseeiftherewasa<p>parentelement,thenforeachofthoseitwouldlookfora<div>parentandsoon:1.foodivpspan{

2color:green;

3}

Thiscantakeaverylongtime(comparatively)becausetherendertreecangetprettymassiveandtherecouldbealotoffalsematches.Ifonlyone<span>inourdocumentexistsinsidea<p>andthereare50<span>sthenourbrowserhasdonealotofneedlessworkbecauseithadtoruleout49ofthem.BEM,introducedearlierinthischapter,avoidsthisproblementirelysinceeveryelementtypicallyonlyhasoneclassappliedtoit.

It’sworthwhilenotingthatoptimizingthispartofaCSSdocumentisprobablynotgoingtogiveyoumuchbangforyourbuck.Thesedays,browsersareprettyexcellentatevaluatingselectors,andworryingtoomuchabouttheefficiencyofyourselectorsinrelationtopageperformanceisprobablyagoodrecipeforinsanity.Knowingabouthowtheselectorswork,however,isimportantknowledgetohavetuckedaway.

SummaryInthissectionwelearnedalittlebitabouthowbrowsersworktoactuallyrenderyourstylesonthepage.It’ssomeprettyinterestingstuff.There’salotmoreyoucandotooptimizewebpages,butasmentionedatthebeginningofthissection,yourbiggestperformancegainswillalmostcertainlybetheoptimizationofyourCSS’deliverytothebrowser.Chasingpainttimesandselectorefficiencymightresultinsomeleanperformancegains,butasourmachinesandourbrowsersimprove,thesebecomelessandlessimportantinfront-enddevelopment.

Ifyouwanttolearnmoreaboutmakingyourpagesrenderefficiently,it’shighlyrecommendedthatyoureadthroughGoogle’sPageSpeedInsights.Thereyou’llfindallkindsofgreattipsforoptimizingimages,prioritizingrenderablecontent,andmuchmore.

StylingSummaryInthischapterwe’vealreadycoveredalotoftopicsandconceptsthatmighthelpyoubetterunderstandthecurrentlandscapeofstylingthefront-end.Thiswaspossiblyoneofthemostdifficultchapterstowritebecausethislandscapeisevolvingalmostdaily,butifyouhaveanyquestionsorwouldjustliketotalkaboutbestpracticestheGoogleGroupforthisbookisagoodplacetostart.

Page 73: Front-End Fundamentals: A practical guide to front-end web development

DependencyManagement

Thereisanentireuniverseoffront-enddevelopmentframeworks,pluginsandtoolsavailableforbuildingapplications.Theopensourcemovementbringswithitahugearsenalforbuildingamazingapplications.Byusingsomeoftheseavailable‘packages’,weareabletodevelopfasterandsafer.

Butyou’llquicklycometorealizethatthebiggestproblemnowisbeingabletoefficientlymanageandkeepuptodateallthepackagesthatyouuse.‘Dependencyhell’isatermyoumayhearfront-enddevelopersuse.Itbecomesevenmoredifficultwhenworkingaspartofateam,asit’scrucialthatalldevelopersonaprojectusethesamepackageversionstoavoidconflictsorbugs.

Donotfear!‘Packagemanagers’areheretosavetheday.Inthischapteryou’llbeintroducedtoseveralessentialpackagemanagersthatarehighlyrecommendedforincorporatingintoyourworkflows.

WhatisaPackageManager?Alldeveloperscreatesoftwaredifferently.Becauseofthis,installing,upgradinganddeletingsoftwarecanbecomeachore.Thatiswherepackagemanagerscomeintoplay.Apackagemanager,itselfapieceofsoftware,keepstrackofwhatisinstalledandallowsyoutoautomatetheprocessofmanagingsoftwareusingastandardAPI.Byadheringtothestandardssetoutbyapackagemanager,softwaredeveloperscanoffertheirpackagestoabroaderaudience.

Node.jsandtheNodePackageManager(npm)ThereareahugenumberofNode.jspackagesavailableforfront-enddevelopmenttasks.Manyofthepopularonesareintroducedinthisbook,suchasGrunt.Forthosewhodon’tknowwhatNode.jsis,here’saquotefromtheirhomepage:“Node.jsisaplatformbuiltonChrome’sJavaScriptruntimeforeasilybuildingfast,scalablenetworkapplications.”Whilewe’renotgoingtobebuildingourownNode.jspackages,wewillneedtoinstallNode.jsitselfsothatwecanuseNodepackages.

TheNodePackageManager(npm)wasnotincludedaspartofNode.jsoriginallybutsinceversion0.6.3itisautomaticallyinstalledforus.npmallowsustoinstallandmanagealloftheNode.jspackagesthatareusedinanapplication.Node.jsisahugeopensourcecommunity.Youcanbrowsethedirectoryofavailablepackagesattheirhomepage,https://www.npmjs.org/.Atthetimeofwritingtherewereover70,000packagesrackingup10milliondownloadsaday.It’sobviousthatnpmisaverypopularresource.

InstallingNode.js

Page 74: Front-End Fundamentals: A practical guide to front-end web development

Let’sgetNode.jsinstalled.Ifyou’reonOSXandusehomebrew(anotherPackageManagerforOSX)thenallyouneedtorunisbrewinstallnodeinthecommandline.

Foreveryoneelse,youcangototheNodehomepageanddownloadthepre-builtbinaryinstaller.Alternatively,youcanclonetheirGitrepositoryandbuildfromthere.Runningthefollowingcommandsshouldgetthejobdone:1gitclonehttps://github.com/joyent/node.git

2cdnode

3./configure

4make

5sudomakeinstall

Theremaybesomedependencyrequirementsandifyou’dliketofindoutmoreoninstallingonyourspecificOS,checkouttheirdocumentation.

Wecanconfirmwe’veinstalledNodecorrectlybyrunningthefollowinginthecommandline:1node--version

Aspreviouslymentioned,npmisbundledwithNode.Toconfirmnpmisinstalled,run:1npm--version

Thepackage.jsonWe’regoingtoneedtocreateafileinourprojectdirectorynamedpackage.jsonthatwillcontainmetadatarelevanttoourapplication.Thisfilewilldefinebasicprojectinformationand,mostimportantly,thepackagedependencies,(i.e.referencestotheNodepackageswerequireforourapplication).Thisfileisimportantbecauseitwillallowbothourselvesandotherdeveloperstoquicklyinstallthedependencieswithasinglecommand,npminstall.Althoughit’spossibletogetawaywithouthavingthisfile,oneofthemostimportantissuesitsolvesisconflicts.IfadeveloperhasadifferentversionofaNodepackagethatisusedinyourapplicationinstalledglobally,thenitmayconflictwithwhicheveroneyouactuallywantthemtouse.

Theeasiestwaytounderstandthepurposeofthisfileistojumpinandcreateit.Let’screateanexampleprojectdirectoryandpackage.jsonfile:1mkdirmyApp

2cdmyApp

3touchpackage.json

Usingyourfavoritetexteditor,openpackage.jsonandaddthefollowing:1{

2"name":"myApp",

3"description":"Anall-roundamazingawesomeapp.",

4"version":"0.0.1",

5"devDependencies":{}

6}

Asthefilenamesuggests,thisfilecontainsJSON.Sofarwe’vedefinedthenameofourproject,itsdescriptionanditsversionusingthestructuremajor.minor.patch.(Formoreonsemanticversioning,checkouthttp://semver.org/).Thisbasicprojectmetadataisrequiredinpackage.jsonfiles.We’vealsodefineddevDependenciesasanemptyobject.

Page 75: Front-End Fundamentals: A practical guide to front-end web development

Thispropertywillbewherewelistthepackagedependenciesforourproject.(Incidentally,youcanautomatethecreationofyourpackage.jsonfilebyusingthecommandnpminitbutit’sgoodtoknowhowtowritethefileyourself!)

InstallingpackagesThisisprobablywhyyouhavenpminthefirstplace.Youwanttoinstallsomething,right?It’sveryeasy.Afteryoufindthenameofthepackageyouwanttoinstall,navigatetoyourprojectfolderandrun:1npminstall<packagename>

Thiswillinstallthepackagetoafoldercallednode_moduleswithintheprojectsdirectory.But,ifyouopenpackage.json,youwillnoticenothinghasbeenaddedtothedevDependenciesobject.It’simportantthatweaddareferencetothepackagetheresothatthenexttimeweoranotherdeveloperwanttosetuptheapplicationfordevelopment,thereferencedpackagesareeasilyinstallable.

Althoughwecouldeditourpackage.jsonmanually,it’sbesttoappendthe--save-devparameterwheninstallingtoautomatetheprocess.Let’strythiswithonethemostpopularnpmpackagesasanexample,express:1npminstallexpress--save-dev

Thisinstallsthepackageonoursystem(inthenode_modulesdirectory)butalsosavesareferencetotheversionwe’veinstalledinpackage.json.Openitupandyou’llseesomethinglikethis:1{

2"name":"myApp",

3"description":"Anall-roundamazingawesomeapp.",

4"version":"0.0.1",

5"devDependencies":{

6"express":"^4.8.7"

7}

8}

Afteryou’veinstalledallofthepackagesthatyouneedthisway,allthatanewdeveloperhastodotomakesuretheyhavethecorrectversionofeverythinginstalledisnavigatetotheprojectdirectoryandrun:1npminstall

Prettycool,huh?

Anotherthingworthmentioningisthatyoucanalsoinstallpackagesglobally.Bydefault,npminstallwillplacepackagesinthenode_modulesfolderofyourcurrentworkingdirectory.Installinggloballywillplacethemodulesoutsideofthecurrentdirectoryandinsteadplacetheminyourglobalfilesystem,(e.g.,/usr/local/lib/node_modulesonOSX).Toinstallapackageglobally,youcanapplythe-gparameter:1npminstall<packagename>-g

Updatingpackages

Page 76: Front-End Fundamentals: A practical guide to front-end web development

Probablythebestpartofapackagemanagerishowcrazyeasyitistoupdatestuff.Becausewhoreallylovesspendingtimeonmaintenance?Thenpmupdatecommandsearchestheregistryfornewerversionsofinstalledpackagesandupdatesthemautomatically.Italsopointsdependentpackagesatthenewversionandremovestheolderversions.Wewanttomakesurethatpackageversionnumbersareupdatedcorrectlysowemustapplythe--save-devparameteragain:1npmupdate--save-dev

Alternatively,wecanupdatejustasinglepackageatatime.Ifwehavealargenumberofpackagesandupdatethemallatonce,itmightbedifficulttodebugtheapplicationifsomethingbreaks.Toupdateaspecificpackagerun:1npmupdate<packagename>--save-dev

ListingpackagesSimplylookinginsidethenode_modulesfolderisnotgoingtotellyoueverypackagethatisinstalled.Installedpackagesmayalsodependonotherpackagesandsotheyeachmayhavetheirownnode_modulesfoldertoo.

Thenpmlistcommandwillgiveyouanicelyformattedhierarchicaloverviewofwhatisinstalledwithversionnumbers.Thecommandalsoletsyoufiltertheresults(i.e.grep)byappendingthepackagename:1npmlist<packagename>

UninstallingpackagesYoucanuninstallpackageseasilyusingthenpmuninstallcommand.You’llneedtoappendthepackagenameand--save-devsothatthepackage.jsonisupdated:1npmuninstall<packagename>--save-dev

GettinghelpYoucanappendthe--helpparametertoanycommandforsomequicksyntaxinformation.Alternatively,prependhelptogetamoredetaileddescription.Forexample,try:1npminstall--help

2npmhelpinstall

BowerWe’veestablishedthatnpmmanagesNode.jspackages.Bower,builtbyTwitter,isapackagemanagerthatisactuallyaNodepackageitself.Boweroffersasolutiontofront-endpackagemanagement.You’llfindmanyofthepopularCSSandJavascriptframeworks,librariesandpluginsareavailablethroughBower.VisittheirSearchpageforalistofalltheavailablepackages.Inasimilarfashiontonpm,Bowerallowsustokeepreferencestowhichpackagesareusedinourapp.

InstallingBower

Page 77: Front-End Fundamentals: A practical guide to front-end web development

Let’sinstallBowerusingnpm:1npminstallbower-g

Noticethe-gflagwhichindicatesthatwewanttoinstallthispackageglobally.Whatthismeansisthatwewillbeabletousethepackageregardlessofthedirectorythatwearein.Weinstallthispackagegloballybecausewe’renotverybotheredwithmaintainingitsversionacrossenvironmentsandwe’dratherbeabletouseitfromthecommandlinefromnewprojectdirectorieswithouthavingtoinstallitagaineachtime.

Thenextstepistocreateafilenamedbower.jsonwhichservesasimilarpurposeaspackage.jsondoesfornpm.Thistime,let’suseahelperfunctiontogetstarted:1bowerinit

Thiswillpromptuswithasetofquestionstowhichtheanswersareusedtocreateourbower.jsonfile.Herearethesettingsusedforourexample:1[?]name:myApp

2[?]version:0.0.1

3[?]description:

4[?]mainfile:

5[?]whattypesofmodulesdoesthispackageexpose?

6[?]keywords:

7[?]authors:JoeFender<[email protected]>

8[?]license:MIT

9[?]homepage:

10[?]setcurrentlyinstalledcomponentsasdependencies?No

11[?]addcommonlyignoredfilestoignorelist?No

12[?]wouldyouliketomarkthispackageasprivatewhichprevents

13 itfrombeingaccidentallypublishedtotheregistry?Yes

Theresultingbower.jsonfileshouldthenlooksomethinglikethis:1{

2name:'myApp',

3version:'0.0.0',

4authors:[

5'JoeFender<[email protected]>'

6],

7license:'MIT',

8private:true

9}

Bydefault,anypackagesinstalledwithBowerwillbeplacedinafoldercalledbower_components.Ifwewanttochangethenameofthisfolder,wecandosobycreatingafilecalled.bowerrcintheapplication’srootdirectoryandaddingthenewdirectoryname.Forexample:1{

2"directory":"vendor"

3}

SearchingpackagesSomethingneatthatBowerdoesisallowustosearchforpackagesfromthecommandline.Simplyrun:1bowersearch<keyword>

Page 78: Front-End Fundamentals: A practical guide to front-end web development

Thiswillreturnpackagesthatcontainthegivenkeyword.YoucanalsoomitthekeywordtogettheentirelistofavailableBowerpackages.

InstallingpackagesJustlikewithnpm,wecaninstallpackagesusingthiscommand:1bowerinstall<packagename>--save

Noticeweuse--saveasopposedto--save-devusedinnpm.Theybothdothesamejobofensuringthatourbower.jsonfileisupdatedwithareferencetotheinstalledpackageanditsversion.Bowerdoesinfactletyouuse--save-dev.Thedifferencebetweenthetwocommandsisthatthepackageswillbereferencedinadifferentobjectwithinbower.json.Whenusingthe--saveparameter,packagesarereferencedinthedependenciesobjectwhereasthe--save-devparameteraddsthemtothedevDependenciesobject.MostoftheNodepackagesinstalledarefordevelopmentpurposes,suchastaskrunning,whichwewilldiveintointhenextchapter.Thatiswhyweuse--save-devinnpm.However,themajorityofthepackagesinstalledwithBowerwillbeserveddirectlytotheclientsofourapplications.Forexample,someCSSfilesoraJSplugin.Youcandefinitelyuseboth--saveand--save-devtoseparatereferencestoinstalledNodeorBowerpackages.It’stotallyuptoyouwhichcombinationsyouuse.

ListingpackagesListinglocalpackagesandavailableupdatesissimple:1bowerlist

UpdatingpackagesToupdatepackagestotheirlatestversion,run:1bowerupdate<packagename>--save

Aswithnpm,thepackagenameisoptionalandifomittedthenallinstalledpackageswillbeupdated.

UninstallpackagesAgain,thisoneisfairlystraightforward:1boweruninstall<packagename>--save

BundlerAnotherveryusefulpieceofthepackagemanagementpuzzleisBundler.BundlerhelpsyoutomanageRubyproject‘gems’.GemsareprogramsandlibrarieswrittenintheRubyprogramminglanguage.Thereareafewusefulgemsforfront-enddevelopmentthatweintroduceinthisbook,soit’srecommendedthatyouinstallBundlertomanagethem.

DependingonyourOSyoumayneedtoinstallRubyfirst.TodosoyoushouldfollowthedocumentationontheRubyhomepage.

NowthatRubyissetup,let’sgetBundlerinstalledfromourcommandline:

Page 79: Front-End Fundamentals: A practical guide to front-end web development

1geminstallbundler

ThisinstallstheBundlergemgloballyonthesystem.Ashasbeenthecasewithourotherpackagemanagers,Bundlerrequiresafileinourprojectsrootdirectorythatwillstoreprojectdependencies.Thefile’snameisGemfileandunlikenpmandBower,hasitsownsyntaxasopposedtousingJSON.Let’screatethefileGemfileandaddasinglelinetoitinourtexteditor:1source"https://rubygems.org"

ThistellsBundlerwheretolookfortheRubygemsthatwewanttoinstall.Alternatively,wecouldrunbundlerinittohaveBundlercreateGemfileforus.

InstallinggemsUnlikenpmandBower,thereisn’tacommandtoinstallgempackages.WeneedtomanuallyedittheGemfileandwritethereferences.Forexample,saythatwewanttoinstallSass.WewouldeditourGemfilesothatitlookedsomethinglike:1source"https://rubygems.org"

2gem'sass','~>3.3.6'

Thentoinstallthepackage,wegototheproject’srootdirectoryandrun:1bundleinstall

Noticethatweusebundleandnotbundler.Thatisnotatypo!Ifyouneedhelpfiguringouthowtowritetheversionnumber,checkouttheGemfilehelppage.Also,it’sworthnotingthatgemsarenotinstalledwithinalocalfolder.Instead,theyareinstalledglobally.

UpdatinggemsThereissomedisagreementinthecommunityaboutwhatpartBundlerplaysinupdatinggems.YoumightfinditeasiesttojustmanuallyeditGemfile,changetheversionnumberandthenrunbundleinstallagain.FormoreinformationonthereasoningbehindsomeofthefunctionalitydecisionsmadeinBundler,checkouttheirPurposeandRationalepage.

UninstallinggemsTouninstallagem,youwillfirstneedtorun:1gemuninstall<gemname>

Then,edityourGemfileandremovethereferencetothegem.

DocumentationSoftwareisonlyasgoodasitsdocumentation.Withoutcleardocumentationofyourprojectyouarelikelytorunintofrustrationswhendeveloping,maintainingortransferringknowledgetonewdevelopers.It’salwaysgoodtostartdocumentingprojectsimmediatelysothatyoudon’thavetoplaycatch-up.Ideally,youshouldcreatedocumentationassoonasyouhavesetupyourpackagemanagers.

Page 80: Front-End Fundamentals: A practical guide to front-end web development

StartbycreatingaREADMEfileintheproject’srootdirectorythatwillexplaintheprocessrequiredtoinstallthepackagemanagers.Aswithalargenumberofprojectsthesedays,wemaywelluseGitHubtomaintainourcoderepository.IfyoudouseGitHub,orthinkyoumightinfuture,youcancreateaREADME.mdfile.The.mdfileextensionstandsforMarkdownandallowsyoutowriteformattedtextfileswithshorthandsyntax.Let’screateREADME.mdandaddsomethingalongtheselines:1#GettingStarted

2

3Beforeworkingonthisapplicationwe'llwanttomakesurewehaveall

4therequireddependencies.Hereisaquickguidetogetstarted.

5

61.InstallNodewith`brewinstallnode`

72.InstallBowergloballywith`npminstallbower-g`

83.InstalllocalNodepackageswith`npminstall`

94.InstallBowerpackageswith`bowerinstall`

105.InstallBundlerwith`geminstallbundler`

116.InstallrequiredBundlergemswith`bundleinstall`

Youcouldcreateascriptthatwouldrunthesesixcommandsbehindthescenesfortheuserbut,aswitheverythinginthisbook,usingthetoolsdirectlygivesyouabetterunderstandingofhowtheywork.Ultimately,thiswillgiveyoumoreconfidencewhenintegratingthemintoyourownprojects.

SummaryInthischapter,welookedatthebasicsofthreeofthemostpopularfront-enddeveloperpackagemanagers:npm,BowerandBundler.You’velearnthowtoinstallthemallandhowtomanagetheirpackages.Wefinishedupbywritingsomedocumentationoftheinstallationprocess.

Packagemanagersareanextremelyimportantpartoffront-enddevelopmentthesedays.Usingtheminallofyourprojectsishighlyrecommended,regardlessofprojectsize,sothatyouareabletomaintainandscalethemefficiently.

Page 81: Front-End Fundamentals: A practical guide to front-end web development

Automation

Timeisakeyfactorinproductivity.Thischapterwillexploresomewaystoautomateyourdevelopmentworkflowsoyouspendlesstimeworkingandmoretimemakingawesome.You’llbeintroducedto‘taskrunners’whichhelpautomaterepetitivetasks.You’llalsodiscoverwaystospeeduptheprocessoflayingfoundationsfornewprojects,andyou’llpickupafewothertipstohelpyoubeamoreefficientdeveloper.

TaskRunnersTaskrunners,alsoknownas‘taskautomationframeworks’,helpyoumanageandexecutesetsofdefinedtasks.Ataskcanbeseenasanyrepetitiveactionyouhavetotakewhendevelopingfortheweb.TaskscanincludeactionssuchascopyingafilebetweendirectoriesorcheckingyourJavaScriptforsyntaxerrors.

Withataskrunner,youcanbuild,previewandtestyourapplicationmuchmoreeasilythanifyoudidalltheworkyourself.Thestrongestattributeoftaskrunnersistheirflexibility,whichmeansyoucanconfigureandrunpre-definedtasksexactlyhowyouwant.Furthermore,ifyoucan’tfindapre-definedtaskthatmeetsyourneeds,youcanevenwriteyourown.

Inthischapteryou’lllearnabitaboutthepopulartaskrunnersGrunt,Gulp,CodeKitandYeoman,includinghowtoinstallthemandhowtoconfigurethemtomeetyourspecificneeds.

Grunt

Gruntisoneofafront-enddeveloper’sbestfriendsandisthemostpopularandwidelyusedtaskrunner.ItisaframeworkbasedonJavaScriptandhasathrivingecosystem.Inaddition,thereareahugenumberofpluginsavailableforGrunt.Ifyou’renotsurewheretostartwithtaskrunners,thenstarthere.

InstallingGrunt

Page 82: Front-End Fundamentals: A practical guide to front-end web development

Let’sworkthroughtheinstallationtogether.We’llinstallGruntusingnpmfromthecommandline.(Ifyouhaven’tdonesoalready,pleasereadtheDependencyManagementchapterfirsttolearnmoreabouthowtosetupandusenpm.)

Thefirsttoolwe’regoingtoinstallisGrunt’scommandlineinterface,grunt-cli.It’sworthnotingthatthisdoesnotactuallyinstallGruntitself.ItonlyprovidesusglobalaccesstothegruntkeywordfromthecommandlinewhichisthenusedtoloadandruntheversionofGruntthathasbeeninstalledlocallywithintheproject.Itisimportanttoremembertoinstallgrunt-cligloballybutgruntlocally.Formoreinformationonglobalvslocalinstallation,checkoutthisarticleoverattheofficialNodeJSblog.

We’llheadovertoourcommandlineandrun:1npminstall-ggrunt-cli

ToverifythatGruntCLIwasinstalledsuccessfullyandthatwecanaccessthegruntcommandwe’llrunthefollowing:1grunt--version

Nowlet’sinstallGrunt.We’llneedtonavigatetoourproject’srootdirectoryfirst:1npminstallgrunt--save-dev

ThiswillinstallGruntlocallyandsaveadependencyreferencetoitfromwithinthepackage.jsonfile.

TheGruntfileNowthatwe’veinstalledGrunt,it’stimetointroduceGruntfile.js.Likepackage.jsonfornpm,theGruntfilebelongsintherootdirectoryofourproject.ItdefinesourprojectandtaskconfigurationsandtellsGruntwhichpluginswewanttousetorunthesetasks.We’renotgoingtodefineanytasksjustyetbutlet’screatethebarebonesoftheGruntfilesothatwecanaddtoitlater.CreateGruntfile.jsintheproject’srootdirectoryandaddthefollowing:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig();

4

5//Defaulttasks.

6grunt.registerTask('default',[]);

7};

You’llnoticethatthisfile,asthefilenamesuggests,isaJavaScriptfile.Allwe’vedonehereiscalledinitConfigwhichinitializesourGruntconfiguration.Thisiswherewewilldefineourtaskslater.We’vealsocalledregisterTasktoinitializeasetoftaskslabelleddefault.TherearenoactualtaskshereyetbutGruntrequiresustodefinethisforittorun.AftersavingGruntfile.jswecantryrunninggruntinthecommandlinefromtheprojectroot.Weshouldgetashinygreenmessagestating:1Done,withouterrors.

ThismeansGruntwasabletorunallofthetasksdefinedindefaultwithoutfailure.

Page 83: Front-End Fundamentals: A practical guide to front-end web development

Yay!We’vejustrunGruntforthefirsttime.ThemoreyouuseGrunt,themoreyou’llloveit!

PopularPluginsTherearethousandsofpluginsavailableintheopensourcecommunityforGrunt.Butthereareafewthathavebecomestaplesforthemodernfront-enddeveloper.Dependingontheproject,youmaynotneedallofthese,butitdoesn’thurttoknowaboutthem.Obviously,theseareonlyaselectfewandmaynotincludeeveryone’sfavorites.

Watch,LiveReloadandConnect

QuitepossiblythemostpopularpluginisWatch.Itallowsyoutorunspecifiedtaskswheneverawatchedfilechanges.So,forexample,youcouldminimizeyourCSSfileswheneveroneofthemchangesorrunJavaScripttestswheneveryousavescriptchanges.TheWatchpluginonlydoesthe‘watching’part.Youhavetospecifyexactlywhichtasksaretoberunwhenafilechangeisdetected.

ToinstallWatch,we’llrunthefollowingfromthecommandline:1npminstallgrunt-contrib-watch--save-dev

EdittheGruntfile.jssothattheplugingetsloaded:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig();

4

5//LoadourGruntplugins.

6grunt.loadNpmTasks('grunt-contrib-watch');

7

8//Defaulttasks.

9grunt.registerTask('default',[]);

10};

AllwehavedonehereisusetheloadNpmTaskscallbacktotellGrunttoloadtheWatchplugin.

TodemonstratehowtouseWatch,let’ssetupsomethingcoolusingLiveReloadandConnect.We’llsetupalocalwebserverthatwillautomaticallyrefreshanybrowserviewingourwebsitewhenafilechangeoccurs.Thisisgreatbecauseitmeanswedon’thavetorefresheverytimeachangeismadetooneofthefiles.TheofficialhomepageforLiveReloaddescribesthetoolas“Ahappylandwherebrowsersdon’tneedarefreshbutton”!.

Usually,whensettingupalocalwebserveryouhavetoconfiguresoftwaresystem-wide.YoumayhaveusedtoolssuchasMAMPoryoumayhaveconfiguredalocalLAMPstackyourself.ButagoodalternativeistouseamorelightweightapproachtotestingwebapplicationsusingacombinationofWatch,ConnectandLiveReloadplugins.

ConnectisanHTTPwebserverframeworkbuiltforNodeJS.It’salightweightstaticwebserverthatprovidespluginsknownas‘middleware’.Connectcomeswithabunchofmiddlewaresuchassessionsupport,acookieparserandmore.

Page 84: Front-End Fundamentals: A practical guide to front-end web development

ThereisaGruntpluginforConnectwhichallowsustostartaConnectwebserversolet’sgetthatinstalled:1npminstallgrunt-contrib-connect—save-dev

WenowneedtotellGruntwhenandhowtousetheplugin.EverypluginyouinstallshouldhaveaREADMEfileavailableinitsrootdirectory(inthiscase,node_modules/grunt-contrib-connect/README.md)whichwilloutlinehowtoconfigurethetask.Let’seditourGruntfile.jsagaintosetuptheconnecttask:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4 //DefinesourConnectwebserver.

5connect:{

6server:{

7options:{

8port:9000,

9hostname:'localhost',

10base:['dist/']

11},

12},

13},

14});

15

16//LoadourGruntplugins.

17grunt.loadNpmTasks('grunt-contrib-watch');

18grunt.loadNpmTasks('grunt-contrib-connect');

19

20//Defaulttasks.

21grunt.registerTask('default',[]);

22

23//Running`gruntserver`runsourConnectserveruntilterminated.

24grunt.registerTask('server',['connect:server:keepalive']);

25};

Here,wetoldGrunttoloadthepluginusingloadNpmTasksexactlyaswedidwithWatch.TaskconfigurationsareaddedwithintheinitConfigcallback.We’vedefinedataskcalledconnectthathasasub-taskcalledservercontainingthesettingsforthetask.We’vedefinedourConnectservertorunonport9000athttp://localhost:9000andtoservethefolderdist(shortfordistribution).

Asdescribedinthecodecommentnearthebottom,runninggruntserverfromthecommandlinewilllaunchtheConnectserveruntilterminated(madepossiblethroughthekeepaliveparameter).Youwillthenbeabletoaccessthewebapplicationbypointingyourbrowsertohttp://localhost:9000.However,thereiscurrentlynodistfoldersolet’smoveontocreatingthatandanexampleindex.html:1mkdirdist

2cddist

3touchindex.html

Openupindex.htmltoaddsomebasicHTMLsuchasthefollowing:1<!doctypehtml>

2<html>

3<head>

4<metacharset=“utf-8">

Page 85: Front-End Fundamentals: A practical guide to front-end web development

5<title>MyApp</title>

6</head>

7<body>

8<p>Helloworld!Welcometomyapplication.</p>

9</body>

10</html>

Now,ifyougotothecommandline,rungruntserverandthenpointyourbrowsertohttp://localhost:9000youshouldseethe“Helloworld”message.

Tofinish,weneedtoconfiguretheWatchtasksothatwhenanychangeoccursinindex.html,abrowserrefreshistriggered.Let’supdateourGruntfile.jstolooksomethinglikethis:1//Projectconfiguration.

2grunt.initConfig({

3//DefinesourConnectwebserver.

4connect:{

5server:{

6options:{

7port:9000,

8hostname:'localhost',

9base:['dist/'],

10livereload:true

11},

12},

13},

14

15//Watchourfilesforchanges.

16watch:{

17options:{

18livereload:true

19},

20html:{

21files:['dist/index.html'],

22tasks:[]

23}

24},

25});

26

27//LoadourGruntplugins.

28grunt.loadNpmTasks('grunt-contrib-watch');

29grunt.loadNpmTasks('grunt-contrib-connect');

30

31//Defaulttasks.

32grunt.registerTask('default',['watch']);

33

34//Running`gruntserver`runsourConnectserveruntilterminated.

35grunt.registerTask('server',['connect:server:keepalive']);

Thefirstthingyoumaynoticeiswe’veaddedourwatchtaskconfiguration.We’vesetupasub-taskcalledhtmlthatwatchesforchangestoindex.html.Wehaven’tactuallytoldWatchtoexecuteanyspecifictasksonceachangeisdetected.However,we’veenabledthelivereloadbooleanbothintheConnectandWatchoptions.ThisbasicallytellsConnectandWatchtouseLiveReloadintandem.Connectcomescompletewiththeconnect-livereloadmiddlewareNodepackageand,asofrecently,Watchnowcomeswith

Page 86: Front-End Fundamentals: A practical guide to front-end web development

LiveReloadserverfunctionalityincludedsoallweneedtodoissetthosetwobooleans.Lastly,weupdatedourdefaulttasksothatthewatchtaskisrun.

Totestthis,you’regoingtoneedtwoterminalwindows.Inthefirst,rungruntserverandinthesecondrungrunt.Youshouldseethefollowingstatusmessagesrespectively:1Running"connect:server:keepalive"(connect)task

2Waitingforever…

3Startedconnectwebserveronhttp://localhost:9000

And:1Running"watch"task

2Waiting…

Makesureyourbrowserislookingathttp://localhost:9000andthenmakeachangetothe“Helloworld”messageinyourindex.html.Don’tforgettosavethefile!Onceyousavethefile,switchbackovertoyourbrowserandyou’llseethatthepagehadrefreshed(probablybeforeyouevenmadeitbackover)andreflectsthechangeyoumade.Neathuh?

ThepowerofWatchreallyshineswhenyoustarttoconfigureitforlargerfront-endapplications.Formany,itbecomesthecenteroftheirautomationworkflow-thetriggertoeverytask.Itreallyisagreatplug-in.

CopyandConcat

Asprogrammers,weaimtodevelopourprojectstobeasmodularaspossible.Thisquicklyleadstoalotoffilesandoneofthebiggestchallengesiskeepingontopofthemall.CopyandConcatareacoupleofthehandiestfilemanagementpluginstoknowabout.

Copy

CopysimplyallowsyoutocopyfilesandfoldersfromGrunt.Copyhasendlessusesbutforthepurposesofdemonstrationlet’screateanexamplescenario.Let’ssaythatwewanttocopysrc/index.htmltodist/index.htmlaspartofourGruntbuildprocessbecausethedistfolderistheonethatistobeservedbyourwebserverandsrciswhereweactuallyeditourcode.Obviouslywitharealapplicationtherewouldlikelybemorefilestocopythanjustasinglefilebutlet’srollwiththisanyway.

Beforegettingstarted,don’tforgettoinstalltheplugin:1npminstallgrunt-contrib-copy--save-dev

ThisishowwemightgoaboutsettingupourGruntfile.jstoreflectthisscenario:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4copy:{

5html:{

6files:[

7{

8src:['src/index.html'],

9dest:'dist/index.html'

10}

11]

12}

Page 87: Front-End Fundamentals: A practical guide to front-end web development

13},

14});

15

16//LoadourGruntplugins.

17grunt.loadNpmTasks('grunt-contrib-copy');

18

19//Defaulttasks.

20grunt.registerTask('default',['copy:html']);

21};

We’vesetupasub-taskwithinourcopytaskconfigurationcalledhtmlwhichwillcopyindex.htmlforus.Thisallowsustoaddthecopy:htmltasktoourdefaulttasklist.SimplyenteringcopyasthetasknamewouldhavealsoworkedasthatwouldtriggerGrunttoexecuteallofitssub-tasks,butit’spreferabletoexplicitlycallthenameofthesub-taskyouwishtoexecutetopreventanyissuesinthefuturewhenyouexpandonyourconfigurations.

Totest,makesurethatthesrc/index.htmlfileexistsandthensimplyrungruntfromthecommandline.Youshouldseethefollowingsuccessmessage:1Running"copy:html"(copy)task

2Copied1files

3

4Done,withouterrors.

Tospecifymoreadvancedfilepaths,suchasusingwildcardsandmatchingonfileextensions,readtheofficialdocumentationonGlobbingPatternswithinGrunt.Copyalsohassomeusefuloptionssuchasencodingtouseaspecificfileencodingwhencopyingormodetospecifycopiedfilepermissions.

Concat

Concatletsyouconcatenatefiles.Concatenationistheactofjoiningthingstogether.Whenoptimizingyourapplicationsforperformance,lookingattechniquestoreducethenumberofrequestsisextremelyimportant.Byconcatenatingfilestogether,youareabletoreducethenumberofrequestsrequiredbyclientstogetatyourcode.

ToinstallConcat,we’llrunthefollowingfromourprojectfolder:1npminstallgrunt-contrib-concat--save-dev

Let’ssaywewanttoconcatenatealloftheJavaScriptfilesthatwehavewithinthefoldersrc/jsintoasinglefile.ThisishowwewouldgoaboutsettingupourGruntfile.js:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4 //ConcatenateallJavaScriptfiles.

5concat:{

6js:{

7src:['src/js/*.js'],

8dest:'dist/scripts.js'

9},

10},

11});

12

13//LoadourGruntplugins.

14grunt.loadNpmTasks('grunt-contrib-concat');

Page 88: Front-End Fundamentals: A practical guide to front-end web development

15

16//Defaulttasks.

17grunt.registerTask('default',['concat:js']);

18};

YoucantestthisbyaddingabunchofJavaScriptfilesintothesrc/jsfolderandthenrunninggrunt.YoumaynoticethatConcatcouldpossiblynullifytheneedforCopyasyoucanspecifythedestinationoftheconcatenatedfile.However,ifyouwantedtorunothertasksontheconcatenatedfilebeforemovingittothedistfolder,youmaywellstillneedCopy.

OneconfigurationoptionofConcatthatyoucanuseisbanner.Itallowsyoutosetastringheaderthatwillbeprependedtothebeginningoftheconcatenatedfile.Itisworthnotingthattheheaderstringisprocessedusinggrunt.template.process.

HereisanexampleofhowtosetupabannerinGruntfile.jsforatypicalapplication:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4pkg:grunt.file.readJSON('package.json'),

5

6//ThebannerisplacedattheheadofourconcatenatedJavaScriptfile.

7banner:'/*!\n*<%=pkg.title||pkg.name%>-v<%=pkg.version%>'+

8'\n*Copyright(c)<%=grunt.template.today("yyyy")%><%=pkg.autho\

9r%>'+

10'\n*<%=pkg.homepage?pkg.homepage:""%>'+

11'\n*/\n\n',

12

13//ConcatenateallJavaScriptfiles.

14concat:{

15options:{

16banner:'<%=banner%>'

17},

18js:{

19src:['src/js/*.js'],

20dest:'dist/scripts.js'

21},

22},

23});

24

25//LoadourGruntplugins.

26grunt.loadNpmTasks('grunt-contrib-concat');

27

28//Defaulttasks.

29grunt.registerTask('default',['concat:js']);

30};

Whatthisdoesisloadinthepackage.jsonJSONfileintoavariablecalledpkgwhichisthenusedtofilloutbanner.Dependingonhowyourpackage.jsonissetup,youshouldseesomethinglikethisatthetopoftheoutputtedscripts.jsfile:1/*!

2*myApp-v0.0.0

3*Copyright(c)2014JoeFender

4*http://www.myapp.com

5*/

LintingwithJSHintandCSSLint

Page 89: Front-End Fundamentals: A practical guide to front-end web development

Lintingistheprocessofanalyzingcodeforpotentialerrors.Intraditionalmethods,youwouldseeJavaScripterrorsintheconsoleifsomethingwentwrong.However,bylintingyourcode,youareabletogetfeedbackonyourcodingqualitydirectlywithinyourGruntbuildprocess.Mostlinterswillgiveyoumoreinformationaboutsyntaxerrorsthanyourtraditionalbrowserconsole.Lintingyourcodeishighlyrecommendedasitcansavealotoftimedebuggingsyntaxerrors.

JSHint

ForJavaScript,weusegrunt-contrib-jshint.ToinstallJSHint,we’llrunthisfromourprojectfolder:1npminstallgrunt-contrib-jshint--save-dev

ThisGruntpluginpassesthroughalloftheoptionsyousetinitsconfigurationtaskdirectlytoJSHint.ThatmeansyouwillwanttobereadingtheofficialJSHintdocumentationforalistofsupportedoptions.

HereisanexampleofhowwegoaboutsettingupourowntypicalJSHintconfigurationinGruntfile.js:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4pkg:grunt.file.readJSON('package.json'),

5

6//ConfiguresJavaScriptlinting.Seehttp://www.jshint.com/docs/options/

7//formoreontheavailableoptions.

8jshint:{

9js:{

10files:{

11src:['src/js/*.js']

12},

13options:{

14curly:true,

15immed:true,

16newcap:true,

17noarg:true,

18sub:true,

19boss:true,

20eqnull:true,

21strict:false,

22globalstrict:true,

23globals:{

24angular:false

25}

26}

27}

28}

29});

30

31//LoadourGruntplugins.

32grunt.loadNpmTasks('grunt-contrib-jshint');

33

34//Defaulttasks.

35grunt.registerTask('default',['jshint']);

36};

Page 90: Front-End Fundamentals: A practical guide to front-end web development

We’vetoldJSHinttocheckalloftheJavaScriptfilesinthesrc/jsfolderaspartofourdefaulttasklist.Totestthis,createanexampleJavaScriptfilethathasadeliberatesyntaxerror.Suchas:1varexample={

2bar:'bar',

3foo:'foo'

4}

Rungruntandyouwillseethefollowing:1Running"jshint:js"(jshint)task

2

3src/js/example.js

44|}

5^Missingsemicolon.

6

7>>1errorin1file

8Warning:Task"jshint:files"failed.Use--forcetocontinue.

9

10Abortedduetowarnings.

JSHintfoundthemissingsemicolonandgaveusaveryclearindicationofwherethesyntaxerrorwas.Becausetherewasanerror,itabortedtheGruntbuildprocess.

Ifyouhaveabuildprocessthattakesseveralsecondstocomplete,bringyourlintertaskasfartowardsthefrontofthelistasyoucansothatyou’llgetsnappierfeedbackaboutpossiblesyntaxerrors.Thatway,you’renotwastingGrunt’soryourowntimegoingthroughabunchoftasksthatyou’lljusthavetogothroughagainonceyoufixthesyntaxerror.

CSSLint

ForCSS,grunt-contrib-csslintisrecommended.AswithJSHint,viewtheCSSLintdocumentationforafulllistofconfigurationoptions.ToinstallCSSLintwe’llrunthiscommand:1npminstallgrunt-contrib-csslint--save-dev

HereisanexampleGruntfile.jstogetCSSLintworkingwithdefaultsettings:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4//ConfiguresCSSlinting.Seehttps://github.com/CSSLint/csslint

5//formoreontheavailableoptions.

6csslint:{

7css:{

8src:['src/css/*.css']

9}

10}

11});

12

13//LoadourGruntplugins.

14grunt.loadNpmTasks('grunt-contrib-csslint');

15

16//Defaulttasks.

17grunt.registerTask('default',['csslint']);

18};

Page 91: Front-End Fundamentals: A practical guide to front-end web development

TotestCSSLintcreateabrokencssfileinsrc/css-perhapssomethinglikethis:1.boo{

2height:100px;

3widths:100px;

4}

Afterrunninggruntyoushouldbegreetedwiththislovelywarningmessage:1Running"csslint:css"(csslint)task

2Lintingsrc/css/example.css…ERROR

3[L3:C3]

4WARNING:Unknownproperty'widths'.Propertiesshouldbeknown(listedinCSS3

5specification)orbeavendor-prefixedproperty.(known-properties)

6Browsers:All

7>>1filelintfree.

8

9Done,withouterrors.

ItisworthnotingthatunlikeJSLint,theGruntbuildprocesswillnotfailwhenthereisacodewarning.Thisseemstobeadesigndecision.

MinificationwithUglifyJSandCSSMin

Minificationistheprocessofremovingunnecessarycharactersfromcode(suchaswhitespaceandcomments)toreduceitsfilesize.TherearelotsofpluginsavailablethatofferdifferenttypesofminificationbutacoupleoffavoritesareUglifyJSandCSSMin.

UglifyJS

UglifyJSisaJavaScriptcompressorandminifier.ToinstallUglifyJS,we’llrunthiscommandfromourprojectroot:1npminstallgrunt-contrib-uglify--save-dev

WecansetuptheuglifytaskinourGruntfile.jswithonlyafewlines:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4//MinifiesourJavaScriptfiles.

5uglify:{

6js:{

7files:{

8'dist/scripts.min.js':['src/js/*.js']

9}

10}

11},

12});

13

14//LoadourGruntplugins.

15grunt.loadNpmTasks('grunt-contrib-uglify');

16

17//Defaulttasks.

18grunt.registerTask('default',['uglify']);

19};

Intheaboveexamplewe’veconfiguredouruglifytasktolookforallJavaScriptfilesinsrc/jsandcompressthemallintotheoutputteddist/scripts.min.js.Bydefault,UglifyJSwillnotonlyremovewhitespaceandcommentsbutwillalsotrytosimplifythe

Page 92: Front-End Fundamentals: A practical guide to front-end web development

codebygroupingtogethercodeofsimilarfunctionality(suchasvariabledeclarations)andbydeletingunusedfunctions.

CheckoutallofthetaskconfigurationoptionsavailableinthepluginREADME,especiallymangle.Bysettingthistotrue,UglifyJSreducesthenamesoflocalvariablesandfunctionstosingleletters.ThiscangreatlyminimizetheamountoftextusedintheJavaScriptfile,thusreducingtheoutputtedfilesize.

CSSMin

CSSMinisprobablythemostpopularCSSminifierGruntplugin.Itusesclean-csstoperformtheactualcompression.

ToinstallCSSMin,we’llrunthiscommandfromourprojectroot:1npminstallgrunt-contrib-cssmin--save-dev

HereisanexamplecssmintaskforourGruntfile.jsthatwilltakealloftheCSSfilesinsrc/cssandminifythemintoasinglefile,dist/styles.min.css:1module.exports=function(grunt){

2//Projectconfiguration.

3grunt.initConfig({

4//MinifiesourCSSfiles.

5cssmin:{

6css:{

7files:{

8'dist/styles.min.css':['src/css/*.css']

9}

10}

11},

12});

13

14//LoadourGruntplugins.

15grunt.loadNpmTasks('grunt-contrib-cssmin');

16

17//Defaulttasks.

18grunt.registerTask('default',['cssmin']);

19};

IfyoulookattheUglifyJSexamplewedidpreviously,you’llnoticethattheyareverysimilar.Yayforstandardization!

Gulp

Page 93: Front-End Fundamentals: A practical guide to front-end web development

Atthetimeofwritingthisbook,gulp.jsisthenewkidontheblock.JustlikeGrunt,Gulpisataskrunner.Theybasicallydothesamething.Someofthekeydifferencesare:

Gulpcallsitself‘Thestreamingbuildsystem’.ItharnessesNode’sstreamstogreatlyincreasebuildtimes.Formoreonstreams,checkoutthestreamhandbook.GulphasasimplerAPI.IthasyouwritingJavaScriptcodeinsteadofwritingconfigurationsinGrunt.Gulppluginsarewrittenforonespecifictaskonly,whereasGruntpluginscanoftendomultiplethings.YoucanfindasearchablelistofGulppluginshere.

InstallingGulpInstallingGulpisfairlysimpleusingnpm:1npminstallgulp-g

Let’sinstallGulpglobally.Next,navigatetoyourprojectrootfolder(orcreateoneifyouhaven’talready)andmakesureyouhaveapackage.jsonsetup.Don’tforget,youcandothisbyrunningnpminitorbyreferringtotheDependencyManagementchapterofthisbook.Then,runthefollowingcommand:1npminstallgulp--save-dev

ThiswillalsoinstallGulpbutthistimelocally.TheimportantpartisthatwemakeareferencetoitinthedevDependenciessectionofpackage.jsonbyusingthe--save-devparameter.

ExampleUsageTodemonstratehowtouseGulp,let’ssetupatasktouglifyJavaScriptfilesusingthegulp-uglifyplugin.We’llstartbyinstallingthepluign:1npminstallgulp-uglify--save-dev

JustaswithGrunt,Gulpalsohasasinglefilefordefiningtasks.We’llcreateafilecalledgulpfile.jsintherootofourprojectandusesomethinglikethefollowingsnippettogetstarted:1vargulp=require('gulp'),

2 uglify=require('gulp-uglify');

3

Page 94: Front-End Fundamentals: A practical guide to front-end web development

4//ThistaskuglifiesourJavaScriptfiles.

5gulp.task('compress',function(){

6gulp.src('src/js/*.js')

7.pipe(uglify())

8.pipe(gulp.dest('dist'))

9});

You’llwanttocreateafewdummyJavaScriptfilesinthesrc/jsfoldertotestwith.Fromthecommandline,rungulpcompresstorunthecompresstaskthatyoudefined.Youshouldthenseethefollowingstatusmessages:1[11:36:18]Usinggulpfile~/myApp/gulpfile.js

2[11:36:18]Starting'compress'...

3[11:36:18]Finished'compress'after8.87ms

Ifyoulookinthedistfolder,you’llnoticethateachoftheJavaScriptfileswecreatedhavebeenuglifiedbutunliketheGruntplugintheyhavenotbeenconcatenated.ThisisbecauseGulpmaintainstheidealthateachpluginshouldonlydoonething.Soifwewantedtoconcatenatefirstandthenuglifywewouldfirstlyneedtoinstallthegulp-concatplugin:1npminstallgulp-concat--save-dev

Then,wecouldupdateourgulpfile.jstolooksomethinglikethis:1vargulp=require('gulp'),

2uglify=require('gulp-uglify'),

3concat=require('gulp-concat');

4

5//ThistaskconcatenatesanduglifiesourJavaScriptfiles.

6gulp.task('compress',function(){

7gulp.src('src/js/*.js')

8.pipe(concat('scripts.js'))

9.pipe(gulp.dest('dist'))

10.pipe(uglify())

11.pipe(gulp.dest('dist'))

12});

Now,onceyourungulpcompress,youwillendupwithasingleconcatenatedanduglifiedfileatdist/scripts.js.

BeforemovingonfromGulp,weneedtoknowhowtosetupfilewatching.Gruntrequiredustodownloadaseparateplugintodothis,whereasGulpincludeswatchfunctionalityfromtheget-go.Let’ssaywewanttowatchforanychangestoourJavaScriptfilesandrunthecompresstaskoncethatoccurs.Wewouldneedtoalterourgulpfile.jsasshownbelow:1vargulp=require('gulp'),

2uglify=require('gulp-uglify'),

3concat=require('gulp-concat');

4

5//ThistaskconcatenatesanduglifiesourJavaScriptfiles.

6gulp.task('compress',function(){

7gulp.src('src/js/*.js')

8.pipe(concat('scripts.js'))

9.pipe(gulp.dest('dist'))

10.pipe(uglify())

11.pipe(gulp.dest('dist'))

12});

Page 95: Front-End Fundamentals: A practical guide to front-end web development

13

14//Watchourfilesforchanges.

15gulp.task('watch',function(){

16gulp.watch('src/js/*.js',['compress']);

17});

18

19//Thedefaulttaskisusedwhen`gulp`iscalledfromthecommandline.

20gulp.task('default',['compress','watch']);

We’vesetupanewtaskcalledwatchwhichisfairlyself-explanatory.Also,tosimplifythingsfurther,wehavedefinedanothernewtaskcalleddefaultwhichrunsourothertasks.Soallweneedtodonowishopovertothecommandlineandrungulp.Now,wheneverwemakeanychangestoourJavaScriptfiles,thecompresstaskwillrunautomagically.

Gulpissimpleandfast.OnceyoulearnitsAPI,theideaofcodeoverconfigisaverywelcomeone.We’veonlytouchedthesurfaceofhowpowerfulGulpcanbe.Formoreinformation,readtheofficialdocumentation.

Sowhichoneshouldyoubeusing?ProbablyGrunt.Gulpisstillonthebleedingedge.ItsecosystemneedsmoretimebeforeitshouldbeconsideredasareplacementforGrunt.Thatbeingsaid,Gulpisanexcellenttoolandhopefullywillcontinuetodevelop.

CodeKit

CodeKitisaMacappcreatedbyBryanJones.Itaimstotakealotofthepainoutofsettingupanautomatedworkflowbyprovidinganarrayofthemostcommonandusefulfeaturesforwebdevelopers:

Hasabuiltinwebserverwhichsupportslivebrowserrefreshingacrossallofyourdevices.Watchesforcodefilechangesandcompilesthemwithlintingandminification.HasbuiltinBowersupportforinstallingandmanagingcomponents.

ThemostappealingpartofCodeKitisthatitisveryeasytogetupandrunning.Allyouneedtodoisinstalltheappanditjustworks.Thereisnofumblingthroughconfigurationfilestryingtofigureoutwhyyourbuildscriptisn’tworkingcorrectly.Ontopofthat,theapp’sUIiscleanlydesignedandapleasuretouse.

RememberthoughthatCodeKitisaMaconlyapp,soifyouareworkingwithotherdevelopersyoumaywanttochecktheycanactuallyrunitbeforedivingin.

Tofindoutmore,watchthesedemonstrationvideosontheCodeKithomepage.Althoughthereisafreetrial,theapprequiresyoutopurchaseaonetimelicenseforfulluse.

Page 96: Front-End Fundamentals: A practical guide to front-end web development

Yeoman

Yeomandefinesapowerfulworkflowthathelpsyoukickstartnewprojectsbyinstallingandconfiguringalmosteverythingyoucouldneedtostartdevelopingyourwebapplications.Itgreatlyreducestheamountoftimeyouneedtowriteboilerplatecodesothatyoucanstartdevelopingsooner.

Yeomanprovidesanecosystemof‘generators’whichcanbeusedforsettingupthefoundationsofdifferenttypesofapplications.Thegeneratorsareopinionated,meaningthatalthoughbeststandardsarefollowedforthemostpart,theymaynotbeperfectlyconfiguredforyourspecificneeds.

ThereisareasonforleavingYeomanuntillast.Itcanbequitetemptingtouseageneratortolaythescaffoldingforyourapplicationwithoutactuallyknowingeverythingthatitisdoing.Ideally,youshouldlearnatleastthebasicsofallthedifferenttoolsthatYeomaninstallsandconfiguresbeforeactuallyusingYeoman.Thatway,itismucheasierforyoutoconfigureyourapplicationafterYeomanhasdoneitsmagic.

TheYeomanworkflowiscomprisedofthreeseparatelymaintainedtools:Yo,BowerandGrunt.YoisthenameoftheactualscaffoldingappfromYeoman,BoweriscoveredintheDependencyManagementchapterofthisbookandGrunthasbeencoveredatthebeginningofthischapter.

InstallingYoYoofferswebapplicationscaffolding,utilizingscaffoldingtemplatesreferredtoasgenerators.AllweneedisnpmtoinstallYo:1npminstallyo-g

OnceYoisinstalled,youwillneedtopickageneratorbestsuitedtoyourrequirements.Asanexamplelet’sinstallgenerator-angular,whichutilizesabunchoffeaturesthatmayberequiredofatypicalAngularJSfront-endwebapplicationworkflow:1npminstallgenerator-angular-g

AsisthecasewithYo,weinstallgeneratorsgloballysothattheycanbeaccessedfromanywhereinthecommandline.Oncethegeneratorisinstalled,wecancreateanewdirectoryforourprojectandfromwithinitrun:

Page 97: Front-End Fundamentals: A practical guide to front-end web development

1yoangular

Youwillbepromptedwithafewquestionswhichwillallowyoutoconfigurewhichtoolswillbeinstalled.Onceanswered,sitbackandrelaxasYotakescareofdownloading,installingandconfiguringeverything.Thereisalotoftextscrollduringthisprocesssomakesureyourterminalwindowisfullscreensothatpeoplearoundyouthinkyou’reworkinginthematrix.

Oncecomplete,you’llwanttospendsometimelookingthroughallofthefilesandfoldersthathavenowbeenplacedinyourprojectroot.Inthisparticulargenerator,awholebunchoftaskshavebeendefinedinyourGruntfile.jsfromwhichyoucanlearnalotaboutsomeofthebestpracticesusedinthedevelopercommunity.

Thereareliterallyhundredsofgeneratorsavailable,manyofwhichareunofficialandcontributedbythecommunity.YoucanviewthelistoverattheYeomanofficialpage.

OtherTipsThegoalofthischapteristohelpyoubecomethemostefficientdeveloperyoucanbe.Tohelpyouonyourway,hereareafewtipsandtrickstomakeyourlifealittleeasier.

zThemoreprojectsyouworkon,themorefrustratingitcanbetonavigatebetweenalloftheirdirectoriesinthecommandline.Enter‘z’,ahandybashscriptthathelpsyoutojumparounddirectoriesinthecommandline.Ittracksyourmostfrequentlyuseddirectoriesandallowsyoutonavigatethembysimplyenteringpartoftheirname.Forexample:1zmyApp

Forexample,thismaytakeyouto/var/www/myAppifthatisadirectorythatyoufrequntlyaccess.

Toinstall,grabthez.shfilefromhttps://github.com/rupa/zandwritesomethinglikethisinyour$HOME/.bashrcor$HOME/.zshrc:1./path/to/z.sh

Alfred.appAlfred,perhapsnamedafterthefamousbutlerofBatman,isaMacappthatcanbeusedasareplacementfortheOSXSpotlight.Amongmanyotherusefulproductivitytasks,Alfredhelpsyousavestimebylettingyousearchtheweboryourcomputerforfilesandapplicationswithafewkeystrokes.AlfredcomeshighlyrecommendedtoanyhardcoreMacuser.However,itisworthnotingthatApplemadesomegreatchangestotheOSXSpotlightinYosemiteandyoumayfindthatsufficientenough.

Page 98: Front-End Fundamentals: A practical guide to front-end web development

Alfredboostsproductivity

ChromeDevToolsOneofthestrongestattributesoftheGoogleChromebrowserisitssetofDeveloperTools-morecommonlyknownasDevTools.Theyareasetofwebdebuggingtoolsdirectlyaccessiblefromwithinyourbrowser.Althoughotherbrowsers,suchasFirefox,docomecompletewiththeirownsetoftoolsfordevelopers,Chromeprobablyprovidesthebestimplementation.Ifyou’venotusedDevToolsbefore,goaheadandinstallChromeandreadtheoverviewdocumentation.

ChromeDevToolsistheessentialwebpagedebuggingtool

SublimeTextLookingforanewtexteditor?Somethingwithasuperslickinterfaceandhugerangeoffeatures?Looknofurther.SublimeTextforMacisquicklybecomingoneofthemostpopulartexteditorsfordevelopers.

Page 99: Front-End Fundamentals: A practical guide to front-end web development

SublimeTexthasasuperslickinterface

Itsflagshipfeature,‘GotoAnything’,hasquicklybecomeoneofthemainreasonsfordevelopersfallinginlovewithSublimeText.BysimplypressingCommand-Pyoucanquicklynavigatetoanyfileinyourproject.Forafulllistofitsfeatures,andguidelinesonhowtoinstall,checkouttheofficialhomepage.

SummaryInthischapter,wetookafairydetailedlookatthetaskrunnerGruntandtouchedonotheroptionssuchasGulpandCodeKit.You’veseenhowimportanttaskrunnerscanbe,andhowtheycanhelpyoubecomeamoreefficientdeveloper.Wethenlookedatafewtipsandtrickstospeedupyourworkflowwhendeveloping.

Page 100: Front-End Fundamentals: A practical guide to front-end web development

Summary

Inthisbookwe’vecoveredthebasicsofcurrentfront-enddevelopmentpracticesallthewayfromwhatmightbeexpectedofaFront-endDeveloperintheworkplacetoautomatingyourdevelopmentworkflow.

Beforeproceedingtoapplytheconceptsyou’vepickedupfromthisbook,makesuretoknowallyouroptionsandpickonethatisabestfitforyouandyourproject.Youmayhavefoundthatsomethinginthisbookconflictswiththewayyou’recomfortabledoingthings.Thatisn’taproblem!Theconceptsandtoolsintroducedmaynotbethebestfitforeverydeveloperorproject.Sobyallmeans,continuetodowhatyou’recomfortablewith!Simplyjustbyreading,you’vetakenanimportantstepinimprovingyourgraspofthefront-endlandscape.

Aswithmostwebtechnology,thefront-enddevelopmentworldchangesrapidly.Soifyou’dliketotalkmoreaboutanythingpresentedinthisbookorjustshareideas,don’tforgetabouttheFront-EndFundamentalsGoogleGroup.

Thankyouverymuchforreading!

Page 101: Front-End Fundamentals: A practical guide to front-end web development

Appendix

Belowisacondensedlistoftheexternalresourcesthatwereferenceinthisbook.

AccessibilityWebAccessibilityChecklist:http://a11yproject.com/checklist.html

AutomationGrunt:http://gruntjs.comGulp:http://gulpjs.comYeoman:http://yeoman.io/z.sh:https://github.com/rupa/zAlfred:http://www.alfredapp.com/

DeploymentContinuousIntegration:http://www.thoughtworks.com/continuous-integration

LearningResourcesFront-endRapport:https://flipboard.com/section/front-end-rapport-bML9ITListofpopularAngularJSresources:https://github.com/jmcunningham/AngularJS-LearningLearningJavaScriptDesignPatterns:http://addyosmani.com/resources/essentialjsdesignpatterns/book/byAddyOsmaniDevelopingBackbone.jsApplications:http://addyosmani.github.io/backbone-fundamentals/byAddyOsmaniResponsiveWebDesign:http://www.abookapart.com/products/responsive-web-designbyEthanMarcotte

FrameworksAngularJS:https://angularjs.orgAngularJSBatarangChromeExtension:https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=enBackbone.js:http://backbonejs.org

Page 102: Front-End Fundamentals: A practical guide to front-end web development

BackboneDebuggerChromeExtension:https://chrome.google.com/webstore/detail/backbone-debugger/bhljhndlimiafopmmhjlgfpnnchjjbhd?hl=enUnderscore.js:http://underscorejs.orgEmber.js:http://emberjs.comExpress:http://expressjs.com/JourneyThroughTheJavaScriptMVCJungle:http://www.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/byAddyOsmani

LanguagesRuby:https://www.ruby-lang.org/

OnlineServicesPrerender.io:https://prerender.ioCanIuse…:http://caniuse.com/#feat=history

PackageManagersNodePackageManager(npm):https://www.npmjs.org/Homebrew:http://brew.sh/Bower:http://bower.ioBundler:http://bundler.io/

PerformanceYahoobestpractices:https://developer.yahoo.com/performance/rules.htmlYSlow:http://yslow.orgCSSMin:https://github.com/gruntjs/grunt-contrib-cssminGoogle’sPageSpeedInsights:https://developers.google.com/speed/docs/insights/rulesUglifyJS:http://lisperator.net/uglifyjs/

SoftwareNode.js:http://nodejs.org/CodeKit:http://incident57.com/codekit/Scout:http://mhs.github.io/scout-app/SublimeText:http://www.sublimetext.com/

Styling

Page 103: Front-End Fundamentals: A practical guide to front-end web development

BEM:https://bem.info/Sass:http://sass-lang.comCompass:http://compass-style.org/Bourbon:http://bourbon.io/Less:http://lesscss.orgStylus:http://learnboost.github.io/stylus/MDNCSSmediaqueries:https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries

TemplatingMustache:http://mustache.github.ioHandlebars.js:http://handlebarsjs.com

TestingWraith:https://github.com/BBC-News/wraithPhantomJS:https://github.com/ariya/phantomjs/PhantomCSS:https://github.com/Huddle/PhantomCSSKarma:https://github.com/karma-runner/karmaJasmine:https://github.com/jasmine/jasmineJSHint:http://www.jshint.comJSHintGruntPlugin:https://www.npmjs.org/package/grunt-contrib-jshintCSSLint:https://github.com/CSSLint/csslintCSSLintGruntPlugin:https://www.npmjs.org/package/grunt-contrib-csslintChromeDevTools:https://developer.chrome.com/devtools

VersionControlGithub:https://github.comgit-flow:http://nvie.com/posts/a-successful-git-branching-model/Githubflow:http://scottchacon.com/2011/08/31/github-flow.htmlSemanticVersioning:http://semver.org/

WebServersMAMP:http://www.mamp.info/en/