mobile web app design tutorial
thank you guys so much. this is really awesometo be on the stage today. over the past year,i've spent a lot of time talkingabout web components, really teaching developersthe basics of the standards and teaching folks how tofocus on building elements. and we're now atthis place where we have this burgeoningecosystem of elements that are out there.
there's a lot of developersout in the open source world who are creatingelements but also got element sets that have beencreated by the polymer team. we've got the core andthe paper elements. and so we're atthis point where we have this flourishingecosystem and i think it's time forus to start to think about the next challenge, whichis how do we leverage that ecosystem to actuallybuild real applications.
and i'm particularlyinterested in figuring out how to build compellingexperiences on mobile. the mobile web has aton of opportunity, but it's one of those areaswhere for web developers, it's always been achallenge to create a real compelling experienceon a mobile device. and so when i was preparing forthis talk, what i wanted to do was just like pop my phone outand look at the applications that i use allthe time, things i
consider sort ofsuccessful experiences. and i wanted to go through themand just sort of catalog what i see as the kind of commonui and ux expectations in a successful app. so what i've gothere is twitter, i've got pocket cast forlistening to podcasts, and i've got rdo. and one thing that struckme as i was doing this is if i just takethese applications
and i put them side by side,even though each of them kind of feels unique when i'mlooking at it in isolation, when they're alllined up like that, it feels like they're justlike a ton of commonalities in their interfaces. and so using twitteras an example here, i want to just catalog someof those common ui patterns that i see. so up at the top,we have a toolbar.
pretty familiar. and oftentimes, ifyou've got a toolbar, you're going to fill itup with some icon buttons. and below that,you've got some tabs for switching between content. you've got a primarycontent area, and oftentimes,you're going to have like an infinite list ofcontents inside of there, or you might just belazy loading more content
as the user isscrolling down the page. and down at the bottom,you've got a secondary toolbar for doing additionalactions of some kind. now, if we takea step back again and we line these appsup again, like when i was looking attwitter a moment ago, it felt like a veryunique experience. it felt kind ofaligned with its brand and it had kind of itsown thing going on.
but again, i linethese guys up and i can see that they allkind of have those same ui patterns going on. they're all kind of doingthe exact same thing. and the reason theyall look the same is because they're allbuilt using an sdk. so these are examplescoming from android, but the same is true ifyou're working in ios. if you're building onone of those platforms,
you already have this sdkthat's available to you, grab a bunch ofcomponents out of it. maybe you kind of tweakthem a little bit, color them differently. but in general,you're using stuff that's already available tocompose your application. now, on the web, we've kind ofnever really had this thing. we've never had appbuilding primitives. we've never hada mobile web sdk,
and i think it's timefor that to change. and i really thinkthat the way that we're going about doing this is usingpolymer and web components. so my goal today is to teachyou how to build mobile web applications usingthese new technologies. and i basically splitthis up into four parts. [? the very ?] part, i'mgoing to show you just how you can structure theui for your application, then we're going to look athow you can transition from one
state of yourapplication to the next. after that, we'regoing to look at ways to make sure your applicationis performant, because that's really crucial for amobile application. and lastly, we'regoing to look at ways you can make sure yourapplication runs offline because if your mobileapp doesn't run offline, then you really don'thave a mobile app. people are oftentimeson their mobile devices
when they're in low connectivityto no connectivity situations. so it's got torun offline for it to be a real, compellingmobile app experience. let's start with structureand just think about ways that we can compose theui for our application. and really, that's thekey word here-- compose. what i want to do is i'm goingto take as many preexisting elements from the polymercore sets to the paper sets and i want to bolt them togetherto build my application.
so this is the appthat we're going to be working from today, justa really simple contacts app that i threw together. and i'm trying to utilizea lot of the same patterns that i was showing in theprevious successful apps that i had before. so you've got the toolbar atthe top with some icon buttons. you start scrollingaround, you're going to get this sort ofinfinite list of content
inside of there. you've got a drawer panel thatyou can pop out for your menu. clicking on anyone of the contacts is going to do kind oflike an animated transition to show you thatperson's contact details. i get it's really nice, coolcondensing header effect as i scroll around. and also, i've got a littlefloating action button down there in the corner.
i can click that, popopen another screen. these are allanimated transitions that i'm using here. now, if you've seenme talk before, you've probably seen me startoff by using this element. anytime i'm buildingan application, it seems like i'malways starting off with this coretoolbar element, which is just a reallysimple container.
it lays out itschildren using flexbox and it's a reallygood place to get started with oneof your screens. and becausecomposition is really the name of the game,what i want to do first is i want to just throwsome additional elements inside of here, and ijust want to compose the ui for my toolbar. so i've dropped a papericon button inside of there.
i've configured itwith an icon attribute to give me the hamburgermenu from that application, and so i'm going toslide out my menu later. i've also dropped adiv inside of here for the title of my application. now, one of the cool thingsabout the core toolbar is that since it usesflexbox, i can kind of take advantage ofthat a little bit. there's things called layoutattributes in polymer,
and what i can dois i can actually tell the title ofmy toolbar that i want it to flex to takeup as much space is it can inside of the toolbar. this is a reallyhandy trick to know because it means thati can then pin controls to the other side of my toolbar. what i want to dohere is actually add a little contextmenu so i can
have things likesettings and feedback. so to do that, i'm going touse another element called paper-menu-button, andpaper-menu-button's pretty interesting becauseby itself, it really doesn't do anything. it's kind of useless. if you just put apaper-menu-button tag on the page, youget really nothing. it only reallycomes into its own
when you start composingother elements inside of it. that's really how youunlock the potential of it. so i've got anotherpaper icon button that i've thrown insideof here, and that's going to give the usersomething to click on. then i'm going to throwin a paper drop down, and that's going to give methis little animated rectangle thing up there. so when the menuexpands, it's going
to kind of like comeout from the corner, expand towards thecenter of the site. the halign attributethat i've thrown on there is going toindicate which direction it should animate from. so here, we'retelling it to animate from the right edge towardsthe center of the screen. lastly, i'm going to throwa core menu inside of here, and that's going to give me theactual menu items that users
are going to select formy sending them feedback. now, the cool thinghere is that each of those elements that i threwinside of my paper menu button is useful on its own. i can use core menu elsewheremy site if i need a menu. what's awesome,though, is when i start to composethese things together, i get different interestingcomplex behaviors. and it's alsoimportant to point out
that i didn't write any css orjavascript to make this happen. i just nipped togetherthese-- oh, yay. thank you, [? demetri ?]. these elements just knowhow to work together because they're app buildingprimitives, which is awesome. and once i'm happy withthe look of my toolbar, then you take all of this markupand i could throw it inside of another elementcalled core-header-panel. and the core-header-panel isjust a really simple container.
it's got a header sectionup at the top, which will hold the toolbar,content area down below. and the cool thing aboutthe core header panel is it only really cares aboutmanaging the scroll behavior from my application. if i put a toolbarinside of it, it's going to make surethat that toolbar stays sticky up there at thetop of the document and all my other content is justgoing to move underneath it.
again, no css or javascriptto make this happen. these are justsmarter primitives. they know how to worktogether like that. now, when someone's actuallylooking at one of my contacts, i want to have this cool, bigshot of addy osmani's face basically, and i want it todo this cool animating effect. so as the personis scrolling down, it kind of collapses,and it's sort of crossfading withthe background image.
and to do that, i'm using acousin of the core-header-panel called thecore-scroll-header-panel. it's basically thesame component, but it adds this nicecondenses attribute, and it gives me thatkind of cool effect. now, once i have the differentscreens for my mobile site laid out in a way that i likethem, i can drop all of this into another elementcalled core-drawer-panel, and that's going togive me a responsive
scaffold for desktop and mobile. and the way thiselement works, it's basically got a drawer area. any content that iplace inside of there is going to endup in my sidebar. it's got a main area. ends up in theprimary content area. and the cool thingis, this element is responsive by default.
so if i'm on my desktop andi just start dragging it out, you'll see the drawerpanel opens there. i can open and close it. i drag this thing out, andwhen i hit a certain size, the toolbar justpops out for me. this is really nice. again, i'm not writing anybreakpoints or media queries to make this happen. the element's just responsive bydefault, which is really nice.
now, at this point, i've builtthe skeleton of an application. i've kind of shown youhow to put the shell around everything, butwhat we're still missing is the lifebloodof our application. we're missing the content. and when i'm showingthese apps earlier, i mentioned that oftentimeswhat they're going to do is they're going to dolike an infinite list, or of a lazy load ofcontent so the user can
keep scrolling throughall of their tweets, or all of their albums,and things like that, and we can achieve the samething in our application using an element called core-list. and core-list is oneof my favorite elements because i feel like it'ssort of the thing that knits all the scaffoldingand the content together in this waythat i really love. the core-list is basicallya virtualized infinite list.
you connect it toa data provider and then it stampsout a template for every single instance inthat data provider's array. so here, i'm sayinglist.data equals some array. i've got objectsinside of that array. each of thoseobjects has a name. and inside my core-list,i have a template element and i'm just binding toeach of those instances as they come in.
it gives me this really,really performant infinite list so i can go throughall of my contacts. now, as i was buildingmy application, i kind of cameacross this thing-- which i'm going toshare with you as a tip if you want to go out andstart using core-list yourself. one of things thatcore-list does is it recycles its children. that's actually howit's so performant.
it makes a fixed set ofchildren and as they're moving, it's pulling them backaround the other way. so if you have image tagsinside of your core-list, you can end up in a situationwhere you're basically racing the network and you'rehaving stale images fly past the screen, andthen they catch up and change, whichsort of looks weird. so i found that there's anelement called core-image which you can use toprevent stale images
in your application. it's pretty easy. you just drop it in here. you give it a preloadattribute, and what that does is it says, hey,if i'm loading an image, i'm not going to displaythe stale image that perhaps was insideof here before. i'm just going to displaya little background color. and so what we can donow is we can actually
have this cool contacts list. we can sort ofrace the networking and you can see theimages loading in, but what you're not seeing isstale images, which is good. the other thing that idiscovered as i was doing this is that it's really important tomake sure to set your core-list scroll target to yourcore-header-panel-scroller. i know that this is alittle bit of a rough edge, but i wanted to makeyou guys aware of it
if you're going to go out andstart hacking on these things today. basically whathappens when you do this is you'retelling the core-list to listen to the scroll eventsthat the core header panel is firing and that way, the twocan work together in harmony. now, there's two ways thatyou can go about doing this. you can either set thescroll target in javascript. you could say list.scrolltargetequals hpanel.scroller,
or you can do this with bindingsif you want to be really fancy and impress your friends. you could just say scrolltargetequals hpanel.scroller. now, this is one of thosethings which, again, i think it's a littlebit of a rough edge. perhaps we might be able toclean this up in the future so that you don't haveto wire this up yourself, but i wanted tomake you aware of it because it was like thefirst thing i wanted to do
was put one of thoselists inside of one of those fancyheaders, and i needed to set up this linkageto make it all work. now, through the beauty ofcomposition, i've taken my list and i've thrown itinside of my scaffold, and i have this really,really cool application now. now, i want to giveyou a quick recap of what we have inside of here. so up at the top, i'vegot a core toolbar.
after that, a paper-icon-button,a paper-menu-button for my contacts menu. i've got acore-header-panel, which is controlling the scrollbehavior for my home page. i've got acore-drawer-panel, which gives me thatresponsive scaffolding so it works ondesktop and mobile, and i've got a core list formy infinite content provider. now, one thingthat's really cool
to do once your applicationhas reached the state where you feel like it's kind ofshaped up a little bit is to think about waysthat you could change it. and if i look at thisand i just imagine perhaps applying a littlecss to that toolbar and perhaps adding a littlebit more content to the list, then i'm really notthat far from something that looks a lotlike inbox, right. all the parts remainthe exact same,
we're just tweaking slightly theappearance of them-- changing some colors, adding alittle bit more content-- but we've now got a verydifferent experience. and because the core listsupports variable height content-- meaning thatour rows don't all have to be the exactsame fixed size-- we can think about throwingcards inside of here. and if we do that, then we havean experience that looks kind of like g+.
and again, none of mymarkup actually changed. i still have a core-toolbar, istill have paper-icon-button, still have paper-menu-button,header-panel, core-panel, and core-list. so my markup remainedthe exact same. the only thing thatchanged was the content that i'm placing inside ofit, which is pretty cool. now in my mind, this isthe power of composition. when we have a mobile sdkthat's full of these really
good generic building blocks,we can build vastly different experiences just by arrangingthem differently and tweaking them slightly. i think that's huge. so let's go back to ourcontacts app for a second. we've got the basic pageskind of figured out, but i haven't really shownyou how to move from one state to the next, and this is adilemma for a lot of folks. they start building components,they get really excited,
they throw themtogether on a page, and then they're like,how do i go from point a to point b. basically,how do i do transitions? and this is one of thoseareas where we're still working on it, buti think we've got some really coolstuff in the pipeline. one of the elements that i'veshown before which i think is really awesome-- i put thislittle experimental badge on it because it also is alittle experimental--
but it's so freakingcool i like to show it. it's this element calledcore-animated-pages, which gives you a pluggablesystem for transitioning of one state of yourapplication to the next. and basically, theway this works is i put some sections insideof my core animated pages. i configure itsselected attribute to tell it which section shouldbe displaying at the time, and i give it a transitionsproperty and i tell it--
or sorry, transitionsattribute to tell it which transitionsi would like it to play as it moves fromone state to the next. and with basicallyjust that i've wired up this is really coolsystem for animating through different statesin my application. so inside of my app, my markupkind of looks like this. i've got a whole bunch of markupthat makes up every single page and it's all kind ofcomposed together.
and so the way thati'm going to transition from one state to the next isactually take all this markup and turn each section of myapplication into a custom tag. keep all that markup,make an element out of it. then i start nestingthose elements inside of core-animated-pages. so i start withmy contacts page. i drop in an info page forwhen you click on a contact and you actually cansee their profile.
so i created a littlecustom transition here called fade scale. it's on my info pageas an attribute. it's also in thetransitions attribute for core-animated-pages. so now when you clickon a contact, which is going to animate up,so you're adding there and then it goes away. and again, for the pagewhere i add a user,
it's basically the same thing. i nest that elementinside of here. i give it a transition. i add that transition toanimated-pages transitions attribute. i click on my floatingaction button now, pops up. i can add a new user ifi want and it goes away. now, another tip that iwant to share with you is something that i cameacross as i was building this.
core animated pagesdoes this thing where if an elementis not displaying, it's going to make it displaynone, which can totally screw it up if it's tryingto figure out its height or do anything like that. so this magical event herecalled core animated pages transition prepare,which is the longest this event name in thehistory of the world. but this eventdoes magical things
because it basically fires themoment that your element goes from being display noneto being display block. and that means that youcan then do all the work that you need to do to makesure that things are measured and have the right heightand everything like that. again, this is one of the thingsthat i'm sure if you see this, you're like dude, thatfeels like a wart, and i totally agree. i think you're right.
and this is one ofthe things that i know the team isaware of and we're going to work on to see if wecan actually smooth this out for people so you don't have todo all that finagling yourself. but again, i wanted tomake you aware of it so if you're following alongwith this video or something afterwards, you want to try andimplement this stuff yourself, you know how to do it. so at this point, i have all thesections of my site together.
they animate, theydo really cool stuff, but really that'sjust animation. we're not really changingthe state, per se. we're missing the other half ofthe puzzle, which is routing, and this comes up a lot. developers are always like,how do i do routing in polymer? and polymer and webfluenz don'treally have an opinion here. we're not going totell you specifically you have to do routing this way.
there's really two waysthat you can go about this. you can do itimperatively in javascript or you can do itdeclaratively with element. and so i'm going to showyou both approaches, and you can decidewhich you prefer. so if you're goingthe imperative route, looks something like this. it's really as simpleas just listening for a route change usingsome sort of routing library.
here, i'm using flatiron director library, so when i hear a route match, itell core-animated-pages, hey, change whichever pageis currently selected. it's pretty straightforward. now, one of the nice thingsabout routing in javascript is it gives you pretty finegrained control if you want it. so if there'sparameters in my route, i can catch those whenthe route matches. i can go fetch moredata if i need to
and feed that to thepage, or i can just pass those parametersto the page itself, be like, here you go, here'sthe parameter that's coming in, and change. so some interesting stuff there. one thing that is pretty cool,which i wasn't actually using my contacts as iexperimented with it. i think it's a really cool idea. it's somethingthat we're probably
going to be using alot more in the future is this notion oflazy loading imports. so actually, let's sayyou've got part of your site that's four or fivepages deep, someone doesn't need all of thosecomponents right away. there's thismechanism in polymer called polymerimport which you can use to just sort ofdynamically import things. so you can add thatto your router.
you can say, hey, whenthat route matches, that far away route, let'simport some of that new stuff, maybe throw a loadingscreen up during that time. and when it's ready, polymerimport gives us a call back and we can change that page. so that's the javascriptway of doing it. there are also projects outthere which do this in markup with elements. in particular, there'sthis really cool one
called app-routerby erik ringsmuth. it allows you tohandle url changes and update the viewsin your application. it handles hashchange urls,as well as htmls history api. so you get eitherflavor that you prefer. the other cool thing is thatit actually already supports core-animated pages anddoing lazy importing with polymer import. but it does all thatunder the hood for you
so you don't haveto do it yourself. so again, two options. it really dependson which flavor you prefer, but definitelytry both out and see what you like inyour application. so this one, i feel like i havemy application pretty sewn up. it does all sorts of reallyinteresting behaviors. i'm pretty stokedwith the way it looks, and now it's time tofocus on performance.
sorry, that's the wrongslide-- performance. there we go. i love that lady's face. one of the areas that peoplerun afoul with polymer often is the route file size. you'll even hear this. people will be like,polymer's too big. it's just bloated, whatever. and there's some ways thatyou can mitigate this.
first is this thing that istole from glen maddern, who is the creator of x-gif, whichis the most important custom element ever made. yeah. thank you. if you haven't seen x-gifyou should take some time and spend it with x-gif. so one really quickwin that you can get is just conditionallyloading the polyfills.
you don't have to load thepolyfills on every platform. there are platformsthat support them. chrome supports it, operasupports it, chrome for android supports it, and hopefullyvery soon firefox. so all we're doinghere's is just checking to see if the differentstandards are implemented on the page. if they are, we justmove right along. if they're not, thenwe load the polyfills.
so this is an easyway to save yourself quite a bit of kilobytes. just conditionally load stuff. that's one trick. and the other thingyou've got to do is you've got to actuallypop open the dev tools and you got to make sure thatyou're inspecting your page. so i looked at thecontacts app after i built it and wasvery proud of it.
i popped open thenetwork panel there and i saw that i was making109 requests-- which is a lot-- and i'm loading 943kilobytes of stuff. now, keep in mind, ihave excluded the images from this network panel,so that's just my code. holy crap, that's a lot. i recognize that 109requests for some of you might be concerning. but what's going onthere is under the hood,
i'm importing elements. those elementshave dependencies. they're importingtheir dependencies, and so on and so on. it's basically thiswhole tree that's growing out of my application. and so to mitigatethis, we created a tool called vulcanize. and vulcanize is a modulewhich will actually
take all of your imports,concatenate them together, smoosh them all together,take all your javascript and your css, mashit all into one file, and allow you tojust load that one thing into your application. now, it is availableas a node module, but if you are not so stokedabout doing everything on the command line, it'salso available in a grunt task and a gulp task.
and for the contacts app,i just used the grunt task. i set it up once and i justnever thought about it again. it just runs everytime i'm about to push to production, which is cool. now, after ivulcanize and i make sure to put my stuff on a serverthat supports [inaudible], my application isnow three requests, which is a significant change. and i've got it downto 114 kilobytes, which
is pretty nice. now, this is all the codefor my entire application. this is all thejavascript, all the css, all the html for myentire application. so i've got it down to114 k, and this number gets actually evensmaller, much smaller, in polymer 0.8, which is cool. now, the last thingwe've got to do, we've got our app tothe point where we're
ready to put it up there,share it with the world, but we've got to make surewe're thinking about offline. because again, if yourapp doesn't work offline, you really don't havea mobile experience. and i know that we've talkeda lot about serviceworker today, so i will talk aboutit again here because it's so freaking awesome andi'm so excited about it. what i did was i added serviceworker to this application. pretty straightforward.
i just checked to seeif serviceworker exists. if it does, i install it. important thing to notehere is that as i'm installing myserviceworker, i've got to make sure that i'm usingthe root scope so that i can catch any request at sort ofthe top level of my application. if you nest your serviceworkerinside of a subdirectory or something likethat, then it's only going to have access tothe request in that scope, which
sort of sucks. you want to put ithigh up if you can. inside my application,as soon as we boot up, i just try and cacheas much stuff as i can. you'll notice that i'm cachingthe vulcanized bundle of all of my elements. so my ui is just likeinstantly available. i'm also caching the initialresponse from my data service so that there are contactsto populate my list there.
and then the otherthing that i did was as the user isscrolling around, i'm dynamically cachingany sort of image that has a hostname from s3.amazon. so as you pass throughan avatar image and call this s3response method. and really, all it's doingis it's fetching that image, it's caching it, and thenserving up for people. so as user kind ofuses my app, it just
consumes things for them. now, if we popthis open in canary and we've got serviceworker running, we started running our app. and what i'm doinghere is at first, i'm just racing to thebottom of my application. and right now, there's noservice worker in play, and so what it's doingis loading all 300 of my contact images at onceand just hammering the crap out
of the network. and you'll seeit's like, oh god, why are you doing this to me. and it finally allstarts to load in. now let's refreshit and see what happens whenserviceworker's in play. let's turn our wi-fioff, refresh the page. you'll see hereover in the column that our assets are nowcoming from serviceworker.
so i race to the bottomof my application. all those things are justcoming in immediately. there's no wait on thoseassets, which is really cool. [applause] so, wrap up. what did we learn? for structuringyour application, for structuring your ui, you'vegot the core and the paper elements.
so you can composethose together to make a really awesomemobile experience. from moving from one state ofyour application to the next, you've got core-animated-pages,and you've also got imperative ordeclarative routing. kind of depends on howyou like to do that. for performance,conditional polyfills. and most importantly,vulcanize all the things. use vulcanize to bundle upas much as you possibly can.
it'll save you a lot. also, considerexploring lazy loading. it's one of thosethings that we're still trying to figure out what'sthe right pattern, what's the right ux there. but it's somethingthat i think we'll be seeing a lotmore in the future, especially in theworld of polymer. lastly, for offline,serviceworker's got your back.
so as that starts to landin the various browsers-- i mean, even today,experiment with it. as it starts to land in variousbrowsers, put it in your app. it's going to be really awesome. if you want to play aroundwith this contacts app, it's available upon the githubs. it totally has a lotof bugs, so please file bug reports, but evenbetter, submit pull requests. if you want to learnmore about polymer
and you're justexcited by everything you've seen this afternoon,as matt mentioned, we're running polymerevents all over the world. we call these polytechnics. i see some of youwearing the shirts, which means you are cool. if you go toitshackademic.com, you can find a polytechnic near you. if you want toparticipate in one,
maybe you want to runyour own, whatever, all the material is up there. if you set one up,please let me know. tweet about it, whatever. it's freaking awesome, so youshould all go check it out. most importantly,polymer-project.org. as you've all been sittinghere, we've actually secretly been updating the website. so there's kind of anew experience there.
it's just a slight-- it'sjust a nicer coat of paint. it's not a full blownreboot of the site, but now it's a lot easierto find the content that you're looking for. the getting started experienceis a lot easier if you just want to get up andrunning with polymer, so definitelycheck out the site, go through someof the tutorials. and i'm looking forward toseeing all the really cool
stuff that you guysbuild, so thanks.
Tidak ada komentar:
Posting Komentar