ThissampleapplicationhasbeenarchivedinfavorofAmplifyJSSamples.Whilethearchivedrepositorywillstillwork,pleasego+1thisfeaturerequestforAWSMobileReactStarterKitsampleifyouarelookingtousethissample.
BootstrapaReactapplicationonAWS.ThissampleautomaticallyprovisionsaServerlessinfrastructurewithauthentication,authorization,websitehosting,APIaccessanddatabaseoperations.ItalsoincludesuserregistrationandMFAsupport.Thesampleusecaseisa"Restaurant"orderingsystemwhereafterauserregistersandlogsintheycanviewdifferentrestaurantmenus,selectitemsandplaceorders.
ThisstarterusestheAWSAmplifyJavaScriptlibrarytoaddcloudsupporttotheapplication.
QuicklinksGettingstartedBuildinganddeployingUsingRegistrationandLogincomponentsinyourAppUsingtheRESTclientinyourAppModifyingExpressroutesinLambdaforyourAppArchitectureOverviewYouwillbebuildingaReactapplicationwithUserRegistration&Sign-inthatallowsyoutoperformCRUDoperationsagainstaDynamoDBtablebyusinganExpressapplicationrunninginAWSLambda.LambdawillbeinvokedbyAPIGatewayusingProxyIntegrationwithgreedypathsthatonlyauthenticateduserscanaccess.TheExpressserverisrunningwiththeAWSServerlessExpressframework.
AWSServicesused:
AmazonCognitoUserPoolsAmazonCognitoFederatedIdentitiesAmazonAPIGatewayAWSLambdaAmazonDynamoDBAmazonS3AmazonCloudFrontPrerequisitesAWSAccount
NodeJSwithNPM
AWSMobileCLI
npminstall-gawsmobile-cliGettingStartedCreateyourbackendresourcesanddownloadthesamplecodeinsideofmy-projectfolder.
$awsmobilestartmy-projectreactFinallyruntheapp:
$cdmy-project$awsmobilerunDone!
PublishtheappTopublishyourapplicationtoAmazonS3andAmazonCloudFront:
$awsmobilepublishAlternativelyusingNPM:$npminstall$npmstartDone!
Enablingfederatedsign-inFederatedsign-incontrolsforGoogle,FacebookandAmazonareprovidedintheuserinterfacebydefault;however,theclientidsfortheseprovidersarenotvalid.Dummyvaluesareprovidedinthefederatedobjectwithinindex.jssothattheuserinterfacecontrolsappear.Youcanremoveanyofthecontrolsbydeletingtheappropriatekeysfromthefederatedobject.
Youmayalsoremovefederatedsign-inentirelybyremovingthe'federated={federated}'statementfromtheReactDOM.rendercallinindex.js.
Enablingfederatedsign-inisathreestepprocess:
Registeryourapplicationwiththeprovider(s).
Theidentityproviderswillrequestinformationaboutyourapplication,andwillsupplyyouwithanapplicationIDandotherkeysthatyourapplication(s)willuseforauthentication.KeepinmindthatsomeprovidersmaysupplyseparateapplicationIDsformultipleapplicationsevenwhentheseapplicationsaresharingAWSresources.
Enabletheproviderforyourapplication.
Therearemultiplewaysofenablingafederatedidentityproviderforyourapplication.
TheAWSMobileCLIprovidescommandsforenablingproviders.
$awsmobileuser-signinenable$awsmobileuser-signinconfigureIfyouselectFacebook:?FacebookAppIDxxxxxxxIfyouselectGoogle:?GoogleWebAppClientIDxxxxxxx?GoogleAndroidClientIDxxxxxxx?GoogleiOSClientIDxxxxxxx$awsmobilepushAWSMobileHuballowsyoutoregisteranidentityproviderbyaccessingtheUserSign-InsectionandselectingtheproviderundertheAddsign-inProviderssection.TheAWSCognitoandIAMConsolesallowyoutoregisteridentityprovidersaswell.Pleaseseetherespectivedocumentationfortheseservices.Onceyouhaveregisteredyourapplicationwithyourfederatedidentityprovider(s)andhaveenabledfederatedidentityforyourapplication,makesuretoincludeyourclientidsinthefederatedobjectinindex.js.Linkstoadditionalinformationaboutfederatedidentityprovidersmaybefoundhere.
UsingthedefaultGreetingsComponentThisapplicationisusingacustomnavwithit'sownlogoutbutton.However,theAuthenticatorcomponentcanprovideadefaultGreetingscomponentwhichdisplaystheusernameandalogin/logoutbutton.YoucanenablethisbyremovingtheGreetingselementfromtheAuthenticator's'hide'arrayinindex.js.
ApplicationwalkthroughOpenabrowsertohttps://localhost:8080andviewtheAuthenticatorcomponent.ChooseSignUpNowandtypeinausername,password,emailaddressandphonenumber.Alternatively,ifyouhaveenabledfederatedsign-inyoucanselecttheproviderandskiptostep5.
Youshouldrecievea6-digitverificationcodeviaSMS.TypethisintothescreenandselectValidate.
NowthatyouareregisteredyouwillberedirectedtotheLoginpage.TypeintheusernameandpasswordthenselectLogin.
YouwillrecieveanotherSMSverificationcode.ThisistheMFAflowuponuserlogin.EnterthecodeintothescreenandselectValidate.
Theapplicationdemonstratesbothloadingsampledataintothedatabaseaswellaslistingdataandnavigation.AsafirsttimeuserpressInsertRestaurantstoloadsamplerestaurantsintotheapplication.
ThesampledataisstoredinsidetheimportedLambdafunction(init.js).ThisdemonstrateshowLambdacodecanbeusedwithExpresstoinsertrecordsintoDynamoDB.TherequestfromtheclienttoAPIGatewayissignedusingAWSSignatureVersion4withthecredentialsreturnedfromAmazonCognitowhentheuserloggedintotheapplication.Refertotheadvancedsectionofthisdocumentformoreinformationonusingthisinyourdesigns.NowthatdatahasbeenloadedselectListRestaurantstodisplaythelistofrestaurantsthatwereaddedinthepreviousstep.Thisalsousesthesigningprocessdescribedabove.
Clickonthenameofarestauranttoseeamenu.
PressOrdertoplaceanorderinthesystem.ThiswilladdanorderentrytoaDynamoDBtableaswellasstoreinformationinthelocalbrowserfortracking.
PressOrdersinthenavigationbar.YouwillseesomeinformationimmediatelyfromlocalstorageandotherinformationreturnedasynchronouslyfromacalltoAPIGateway.
Thenavigationbarisoptimizedtoworkacrossdesktopandmobilebrowsers.ItwillshoweitheratthetopofthepageorinacollapsiblebarontheleftformobileformfactorsSelectLogoutinthenavigationbartoreturntheusertothehomepage.BuildinganddeployingThefollowingstepsoutlinehowyoucanbuildanddeploytheapplicationusingtheS3andCloudFrontresourcescreatedbytheImportphaseabove:
Navigateto./aws-mobile-react-sample/clientandbuildforproductionbyrunning:
$awsmobilepublish
Thiswillautomaticallyrunthenpmrun-scriptbuildcommand,uploadyourapplicationtoAmazonS3andAmazonCloudFront,andopenyourdefaultwebbrowsertotheAmazonS3staticwebhostingpage.
AutomatingBuild&DeployIfyouareusingaCI/CDprocessyoumaychoosetoautomatethisprocess.ThefollowingshowshowtouseawebpackpluginwithAWSCredentialstoautomatedeploymenttoS3:
Navigateto./aws-mobile-react-sample/client/directoryandeditwebpack.config.jsfile.Addthefollowingtothetopofthefile:constS3Plugin=require('webpack-s3-plugin');Addthefollowingasanentrytotheplugins:[]sectiontowardsthebottom:newS3Plugin({//Onlyuploadcssandjsinclude:/.*\.(css|js)/,//s3Optionsarerequireds3Options:{accessKeyId:AWS_ACCESS_KEY_ID,secretAccessKey:AWS_SECRET_ACCESS_KEY,},s3UploadOptions:{Bucket:'MyBucket'}})NOTE:ReplacetheAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEYandMyBucketwithappropriatevaluessuchasyouraccountkeysforautomationandtheS3bucketcreatedduringtheimportprocess.
Savethefileandrunthefollowingcommandtoinstalltheplugindependency:npminstall--savewebpack-s3-pluginRunthefollowingcommandtobuildanddeploytoS3:$awsmobilepublishAdvancedUsageUsingtheRegistrationandLogincomponentsinyourapplicationTheRegistrationandLogincomponentsleverageAWSAmplifytomakecallstoAmazonCognitoUserPoolsandAmazonCognitoFederatedIdentities.AsanexampleofusingitinyourownapplicationfirstcreateaReactapplicationwithCreateReactApp:
npminstall-gcreate-react-appcreate-react-appmy-appcdmy-app/npmstartIftheapplicationrunssuccessfully,copytheAuth,configurationandcssfoldersfrom./aws-mobile-react-sample/client/srcto./my-app/srcthatwascreatedbyCreateReactApp.Nextcopyindex.jsandMain.jsxfrom./aws-mobile-react-sample/client/srcto./my-app/src.EditthecopiedMain.jsxsothatthereturn()functionmatchesthebelowcode:
return(<div>{!logOut&&(<BrowserRouter><div><NavbarclassName='nav-bar'brand='WebApp'right><NavItemonClick={this.signOut}>Logout</NavItem></Navbar><App/></div></BrowserRouter>)}{logOut&&(<AppRouteauthStatus={false}/>)}</div>);Next,fromyour./my-appdirectory,run:
$npminstall--saveaws-amplifyreact-router-domreact-materializereact-transition-group@^1.1.3semantic-ui-reactcss-loaderEditMain.jsxandcommentoutthefollowing:
//importHomefrom'./Home';//importMenufrom'./API/Menu';//importOrdersfrom'./API/Order';AlsoaddimportAppfrom'./App';tothetopofMain.jsxandsavethefile.
Editindex.jsandreplacetherequire('file-loader....')statementtowardsthetopwith:
require('file-loader?name=[name].[ext]./index.html');Finallytoaddthestylingtothepageedit./my-app/public/index.htmlandaddthefollowingtothehead:
<linkrel="stylesheet"href="https://fonts.googleapis.com/icon?family=Material+Icons"><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/css/materialize.min.css"><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css">Andaddthefollowingtothebody:
<scriptsrc="https://code.jquery.com/jquery-2.1.1.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.98.0/js/materialize.min.js"></script>YoucannowrunyourapplicationcreatedwithCreateReactAppwithanewloginpageadded:
npmstartTheapplicationshouldstartandallowyoutoregisterusersandlogintakingyoutothenormalpagecreatedwithCreateReactApp.
UsingAWSAmplifytocommunicatewithAPIGatewayThesampleapplicationusesAPIGatewayandLambdatorunanExpressapplicationwhichreadsandwritestoaDynamoDBtable.IncludedinthesampleisahelperfunctionformakingsignedrequeststoAPIGateway.We'llshowhowtousethishelperformakingunauthenticatedrequeststoAPIGatewaybelowandyoucanusetheLoginexampleabovetogetauthenticatedcredentialswhichthissamplewoulduse.
AswiththeprevioussectionfirstcreateaReactapplicationwithCreateReactApp:
npminstall-gcreate-react-appcreate-react-appmy-appcdmy-app/npmstartIfyoudidn'tdotheprevioussection,copyconfigurationfrom./aws-mobile-react-sample/client/srcto./my-app/src.
Edit./my-app/src/App.jswiththefollowingimportsatthetop:
importLinkfrom'link-react';import{Table}from'semantic-ui-react';importawsmobilefrom'./configuration/aws-exports';importAmplify,{API}from'aws-amplify';Amplify.configure(awsmobile);**NOTE:TomakecallstoAPIGatewaythroughAWSAmplify,youneedyourIdentityPoolIDinaws-exports.js.Forfurtherdocumentation,refertoAWSAmplifyModifytheAppcomponentlikeso(NOTE:youareNOTmodifyingtherenderfunctionYET):
classAppextendsComponent{state={data:[]}fetch=async()=>{this.setState(()=>{return{loading:true}});API.get('ReactSample','/items/restaurants').then(resp=>{this.setState({data:resp});console.log("responseis:",resp);}).catch(err=>console.log(err))}}//renderlogicbelowrender()....morecodeNow,changetherender()functionlikeso:
render(){return(<divclassName="App"><LinkonClick={this.fetch}>Listrestaurants</Link><div><div>{(<Table><Table.Header><Table.Row><Table.HeaderCell>Name</Table.HeaderCell><Table.HeaderCell>Address</Table.HeaderCell><Table.HeaderCell>Contact</Table.HeaderCell><Table.HeaderCell>Rating</Table.HeaderCell></Table.Row></Table.Header><Table.Body>{this.state.data.map((data,idx)=><Table.Rowkey={idx}><Table.Cell>{data.name}</Table.Cell><Table.Cell>{data.address}</Table.Cell><Table.Cell>{data.phone}</Table.Cell><Table.Cell>{data.rating}</Table.Cell></Table.Row>)}</Table.Body></Table>)}</div></div></div>);}}exportdefaultApp;Savethefile.Finallyinstallthedependencies:
npminstall--savelink-reactsemantic-ui-reactDependingonifyouwanttodoAuthenticatedorUnAuthenticatedrequeststoAPIGateway,youwillneedthefollowingmodification:
AuthenticatedRequests
Note:Ifyouaredoinganauthenticated,signedrequestyou'llalsoneedtoperformacouplemoresteps.Firstinstallquerystring-browser
npminstall--savequerystring-browser@^1.0.4Nextyouwillneedtoconfigurethisasawebpackalias:
resolve:{extensions:['.js','.jsx'],alias:{querystring:'querystring-browser'}}ForourCreateReactAppsampleyouwillneedtomodifyeitherwebpack.config.dev.jsorwebpack.config.prod.jsinthe./my-app/node_modules/react-scripts/configdirectory.Lookfortheresolve:fieldinsidemodule.exportsandaddthequerystring:'querystring-browser'entryunderthealiasfield.
UnAuthenticatedRequests
NavigatetotheAPIGatewayconsole,clickontheReactSample-MobileHubAPIandselectResourcesonthelefthandsideofthepage.Underthe/itemsnodeselectANYandthenclickonMethodRequestintherighthandsideoftheconsole.ClickthedropdownlabeledAuthorizationandselectNONE.PresstheUpdatetickboxtosaveyourchanges.
Inthesamepartoftheconsole,selectthe/items/{proxy+}nodefollowedandclickANYandthenMethodRequest.RepeattheprocessofsettingAuthorizationtoNONEandsavingyourchange.
NextdeployyourchangesbyselectActionsatthetopofthepage,thenDeployAPIandselectDevelopmentastheDeploymentstage.ClickDeploy.
Additionallyyouwillneedtomakeanalterationtothe./my-app/src/App.jsbychangingthethis.setState()functionfrom:
this.setState({data:resp});To:
this.setState({data:resp.data});RunyourapplicationFinally,aftermakingyourmodificationsforeithertheAuthenticatedorUnAuthenticatedrequestrunthefollowingcommandtolaunchyourCreateReactAppagain:
npmstartClickListrestaurantsatthetopofthepagetousetheAWSAmplifyAPIcomponent.
ModifyingExpressroutesinLambdaThesampleapplicationinvokesaLambdafunctionrunningExpresswhichwillmakeCRUDoperationstoDynamoDBdependingontheroutewhichispassedfromtheclientapplication.Youmaywishtomodifythisbackendbehaviorforyourownneeds.Thestepsoutlinehowyoucouldaddfunctionalityto"createaRestaurant"byshowingwhatmodificationswouldbeneededintheLambdafunctionandthecorrespondingclientmodificationstomaketherequest.
Addthefollowingfunctionintoapp.jsbeforethesectionthatsays*Restaurantmethods*varputCallback=function(err,data){if(err){console.log(err)}}functioncreateMenu(restaurant_id){varitem1={}item1.id=uuid.v1()item1.restaurant_id=restaurant_iditem1.name="GoldenRatioBaconSkewers"item1.description="Fibonaccionastick!Whodoesn’tlikebacononastickthatkeepsgoing?"item1.photos=[]dynamoDb.put({Item:item1,TableName:MENU_TABLE_NAME},putCallback)varitem2={}item2.id=uuid.v1()item2.restaurant_id=restaurant_iditem2.name="AbelianCucumberSalad"item2.description="Acoolandrefreshingsaladforanyhotsummerday."item2.photos=[]dynamoDb.put({Item:item2,TableName:MENU_TABLE_NAME},putCallback)varitem3={}item3.id=uuid.v1()item3.restaurant_id=restaurant_iditem3.name="Chili-CucumberorientableCorn"item3.description="Feellikeyou’reconnectedtonaturewithcornthatwrapsaroundyourbelly."item3.photos=[]dynamoDb.put({Item:item3,TableName:MENU_TABLE_NAME},putCallback)varitem4={}item4.id=uuid.v1()item4.restaurant_id=restaurant_iditem4.name="FiniteShort-RibFields"item4.description="Noutensils!BBQisfingerfood!"item4.photos=[]dynamoDb.put({Item:item4,TableName:MENU_TABLE_NAME},putCallback)varitem5={}item5.id=uuid.v1()item5.restaurant_id=restaurant_iditem5.name="EasyFractalSalad"item5.description="Thissymmetricpastasaladfeaturesfeta,artichokehearts,andkale."item5.
评论