DAVID J. MALAN: Hello, everyone.
Thanks so much for coming to a CS50 seminar.
So we're here with our friend Charlie Cheever,
who was a classmate a few years after me, class of 2003, who started off life
here at Harvard, went on to Amazon, went on to Facebook, went on to Quora,
and now is focusing on Exponent and developing
JavaScript-based applications that work especially well for the mobile web.
So as we dive into CS50's own final projects,
this is particularly apt because the world is only getting better and better
at actually developing mobile software and making it easier and easier,
and it's in large part thanks to frameworks like this.
So welcome to our friend Charlie.
[APPLAUSE]
CHARLIE CHEEVER: Thanks.
Hi.
I'm Charlie Cheever.
And I'm going to talk to you about building
native mobile apps in JavaScript.
I think if you are a CS50 student and you have your final project coming up
and you want to build a mobile app, this is probably a pretty good way
to do it because you only have to learn JavaScript.
But you can get really nice looking and feeling native applications this way.
So I'm going to be talking about this product I
work on called Exponent, which is built on top
of something called React Native, which uses JavaScript
for building mobile apps.
A little about me-- I went to Harvard and was class of 2003.
So I took CS50 in 1999.
It was a little bit more about weeding people out
than being the biggest class and teaching people stuff then.
But it was still fun.
I was a CS concentrator.
After I graduated, I got a job working as a programmer at Amazon.
I did that for about two and a half years,
and then I went to Facebook in 2006 and worked on a whole bunch of stuff
there and left in middle of 2009 and started Quora, which
is like a question-answer service.
And then I left that a few years ago and started
working on this project, which basically came out
of-- I was working on our mobile apps at Quora,
and there were all these problems building them.
And I wanted to make that better.
So let me give you a brief history of mobile development,
just so how we ended up in the current state of the world.
Back in 2007, the iPhone came out.
And when it came out, you couldn't really build apps on it.
All you could do is build websites.
And most people didn't build special websites for it right away.
So even in this screenshot, you can see that this is basically
the desktop website of the New York Times.
And so it's cut off.
And you're going to have to do a lot of pinch to zoom and scrolling around
and stuff to see everything.
But this was the main way people kind of used everything
that wasn't built into the iPhone, was you just went to a website.
If you look at this plus button here, there
was a way you could sort of store a website to your home screen
and use stuff that way.
But no one ever really did that.
And so that didn't work that well for developers.
So then in 2008, Apple, with sort of the iOS 2.0 release,
made a way that you could build native apps for iPhone.
And you used Xcode, and you wrote Objective-C.
And you could submit them to the App Store.
And after two weeks, they would maybe get approved by Apple,
and they would show up in the app store, and people
could download them that way.
And then when Android came out, you could
use Java to basically do the same thing on Android.
You could write an app in Java, and then submit to Google,
and they'd distribute it in the Play Store.
So there were a bunch of challenges with this, though.
And I think at the highest level, what basically
happened is all this progress that we made with the web in terms
of making development go faster and be easier and more accessible to everyone,
we kind of went back in time to, like, 1993, before the web was invented,
with this native app.
So you basically were writing this native code,
but you were managing your memory manually.
So you're worrying about allocating and deallocating things.
That's gotten better since then.
But it was still a thing you had to worry about at this time.
And then the biggest thing is when you started making your app,
if you made it one screen, it would kind of take you just a few seconds
to compile and then not too long to copy over to the device,
and it would work fine.
But then as you added a second screen, a third screen, and then
more abstractions and libraries to help you
reason about your code your writing, and your app
kept getting bigger and bigger, every time
you made a small change to your app, rebuilding it would take minutes.
About a year or two ago, somebody who works at Facebook on the mobile app
there told me that building the iPhone app takes 45 minutes there.
So if you change something there and you want to build it,
you wait 45 minutes before it's done.
And they have specialized hardware and build farms and stuff.
And they have ways of just working on pieces of it,
and then combine them together.
But nonetheless, it's a big challenge that you
have to manage as your app gets bigger and bigger.
So dealing with anything complex is really hard and really gnarly.
It's also hard to reuse anyone else's code.
The libraries that people distribute that get
included in Xcode projects and Android Studio projects,
they tend to be really bulky.
And so you can't include that many of them.
So you might include one networking library or one UI library or something.
But it's really hard to just willy-nilly include
a library here, a library there, and reuse lots of pieces of stuff.
Another thing that-- it's hard to understand this if you've ever done
websites or done any kind of modern programming.
But the way that you would do layout with this stuff
is you would do a lot of arithmetic.
So you'd sort of say, I want a box here.
And then I want something inside it.
So x plus 10, comma, y plus 10.
And then by the time you start to get a complex layout that
was sort of a thing inside of a thing that's nested,
and there's a scroll view, and then there's a keyboard that comes up,
you have lots and lots of math that you're
doing manually to compute layout.
And so people have come up with ways to make this a little bit better
over time.
But it's also gotten harder because when mobile phones first came out,
everything was the same screen size.
There was one iPhone, and it was a certain size.
And if you just built for that, you were fine.
But now, there's all kinds of different iPhones,
and there's almost infinity different Android sizes.
So worrying about that, it's unreasonable to worry
about this in a generalized way.
And then once Android got popular and the market
was split between iPhone and Android, you
had this world where if you built an iPhone app, then
you had to build an Android app.
But you had two separate code bases.
And so that was actually, in some ways, the biggest problem because then you
had this ongoing maintenance nightmare, where if you want to add a new feature,
you're doing twice the work.
And in practice, at most companies, the Android team
ends up being like-- they have no creativity or anything like.
Their assignment is whatever the iPhone team does, just copy them.
And then it's just a really boring job that no one wants to do.
It's hard to get good people and retain them.
And it's expensive.
And so there's a lot of problems with that.
So then dealing with all the frustrations of this,
people decided, oh, there must be a better way.
We can't deal with all these things.
What can we do?
So then smart people scratched their head and said, hey, wait a second.
All these phones are coming with a web browser.
We can embed a web view inside our apps.
Web code we can write at once.
It'll run anywhere.
All of our developers are used to writing web stuff.
We're familiar with HTML, JavaScript, CSS, stuff like that.
And then maybe we can wrap stuff in native.
So people made libraries to do this better.
The most popular one is probably called PhoneGap,
then it got renamed to Cordova.
And then people built this thing called Ionic
on top of that that's pretty good.
That's the way a lot of apps are built. And the advantages are pretty obvious.
You write code once.
It's familiar-- because it's web stuff-- if you're a developer.
And then it kind of works on both platforms.
The problems are that the look and feel is never quite right.
If you use mobile websites, you kind of know
that they always feel a little bit janky,
and you're trying to scroll or drag something around.
And it just jerks or snaps to your finger.
And the way the scrolling feels isn't quite right.
And just gestures and animations, in particular, just aren't right.
And then also, performance just tends to be subpar.
And I don't know exactly why that is.
But every company that I talked to from 2009 to 2012 that had a native app
and was trying to do a hybrid app like this,
they found that all of their metrics around engagement and people
using their app would go down when they launched
this web-based thing because for whatever reason,
it just wasn't as fast and as snappy.
And then people would kind of lose interest
and go on to doing other things.
The other thing that's hard about it is a lot of things
that were really great on these phones were that you had a camera
and you could be taking pictures with it.
And they had sort of mapping capabilities and stuff like that.
And it's really hard to integrate those directly into a web view.
And so what most people who built hybrid apps would do
is if you had a camera function, it would be in its own separate screen,
separate from the rest of the app.
And if you had some sort of maps thing, they'd build that in Native separately.
And so you'd kind of end up building all the hard parts of your app
in sort of the native way, which is OK.
But you don't get the seamless experience.
You kind of get this experience where you have some web stuff,
and then you have one screen that's either a camera or a map
or something like that.
So this was really popular for a while.
But then a lot of people started to realize
that there were all these downsides to it, especially in terms of performance.
And so I think Facebook made this big announcement
that they were moving away from it.
I think Mark Zuckerberg said this quote that I put here--
"Betting completely on HTML5 is one of, if not the biggest strategic mistake we
ever made."
And that really turned the tide away from people
who are serious and thinking they were building real mobile apps.
It pushed them all back into doing native stuff, for the most part.
But I just talked about all the problems with doing native stuff.
And so where do we go from here?
There's a couple ideas that people have.
And one is there's a lot of people who think that the web browser is going
to get a lot better and be really good.
And there's a bunch of smart people at Google working on this.
And there's people working on this at Apple and other things.
And they are getting better.
Phones are getting faster, too, which means that even slow web browsers are
faster when they're running on super fast iPhone 7's.
And there's some reasons to think that this will happen.
I saw when Vine shut down yesterday, some guy at Google said,
oh, I spent one hour hacking and made almost a complete clone of Vine
using progressive web app technology.
And then I tried to open it on my phone, and I got this error message
that MediaRecorder is not supported by this browser.
Try a different version.
And that just kind of demonstrates a lot of the problems with this approach.
One, there's all these different browser vendors.
And so this technology can't move forward that
fast because you're kind of waiting for a standards body to approve stuff,
and then for all the different vendors to implement it.
And so you're always kind of using the lowest common denominator, which
moves really, really slowly.
It's still, you can't reliably play video inline
across all different web browsers.
And so this feels like it's a real long-term thing.
There's also something where progressive web
apps tend to try to download pieces of themselves piece by piece.
So it'll download just what you need to get started.
And then as you go navigate to different screens and stuff like that,
it'll just download the code for those.
And that makes a lot of sense in some ways.
But in practice, a lot of people have found
that if you're in places with spotty internet connections,
it actually doesn't work very well because when you actually
have to download more than just a tiny bit of data
to actually get functionality in an app, the trade-off isn't worth it.
And you'll get a more reliable app if you just download everything
up front, and then just download the minimum amount of data
necessary to sort of fill in what an application is,
like the messages in iMessage or something like that,
instead of downloading all the scaffolding for a screen.
There was a company in India called Flipkart,
which is sort of like the Amazon of India,
although I guess Amazon is becoming the Amazon of India now.
But they notably, a few years ago, decided
they were going to switch entirely to a progressive web app.
And they spent a lot of effort making it really,
really good and being best in class.
And then about six months ago, I think, they
announced that they were switching back to doing a native app because they just
weren't getting the results that they wanted.
So there's problems with that.
The other approach that people were taking is sort of going pure native
and writing Objective-C or Swift.
And that's getting better.
Swift is a cool new language.
It has a lot of nice features.
Google keeps making the Android Java development
experience better and more reasonable.
But there's still just really big, fundamental problems,
I think the biggest of which, in addition to all the ones I mentioned
before, is that if you're trying to organize a team to build something,
from a product perspective, you want to take a feature-- like, say, oh,
here's like the profile screen.
And you want to say, hey, here's a small group of people.
That's your thing.
Designer, engineer, product manager, or maybe another engineer-- go build that.
Figure out what it needs to be.
Talk to everyone else.
Get buy-in.
And then execute on it.
But when you have a really deep stack on iPhone
and then a really deep stack on Android, it's
really unreasonable to expect lots of small teams to know that,
especially when those stacks change pretty quickly.
Swift just came out.
So all those people who knew Objective-C, now they're like,
so I have to learn Swift.
Oh, there's all these new API coming out in iOS 10.
Do I have to learn those?
And so it's not a static thing.
There's actually a bunch of work you have to do on an ongoing basis
to stay an iPhone expert or an Android development expert.
So from a technical perspective, you pretty much
have to organize your team by iPhone team, Android team.
But then you lose that organization by product feature.
And so then you end up having to have someone
spec out exactly what the profile screen is going to look like,
and then hand those specs to your iPhone team and your Android team.
And that makes that loop of, hey, OK.
We built this, and now we're trying it.
Oh, people don't like it.
We need to change this and this and this.
It makes that loop a lot longer.
And so products take longer to develop, and they're not as good.
And so there's really a bunch of organizational problems
that come from just the fact they you're trying
to develop in these two totally separate stacks.
So that's not great.
So is there a solution?
Somebody's got it.
There's so many smart people in the world.
This is such a big problem.
Everyone's gonna have mobile phones.
How do we go forward?
So I think the most promising thing on the horizon right
now is-- not even on the horizon.
It's here now.
It is called React Native.
Facebook announced this at a conference in 2015.
And I think within two days, it had 35,000 stars on GitHub.
I think it has 40,000 now.
So people are really excited about it.
And it basically works where it lets you write
your UI in JavaScript, but instead of generating web stuff, which
has all these performance problems, you're
actually generating the native UI views, like UIKit in iOS or Android Fragment
activities and stuff and views on Android.
So the way that apps look and feel and perform
is just like if you're writing in pure native,
but the development experience is that you're
writing mostly one single UI code base and getting the same result on both.
And so you can develop much more quickly,
and you can kind of work mostly in one codebase
but get a lot of the same benefits.
The way this works is it's a library that you
can include in an Xcode project or an Android Studio project.
And you can also integrate directly with native views.
So if you wanted to include a map or a live camera view
or do something like a Snapchat filter, you could write native code
and have it integrate seamlessly with the rest of your app
that you're writing in JavaScript.
So it's pretty cool.
And it actually in some ways can be more performant than traditional native
because naturally, the way that it's organized
is that you run the JS VM for this stuff in a separate thread,
often in another core because mobile devices are typically multi-core
these days.
And that sends commands over to the main UI thread,
like, put a view here that has a red border that's two pixels wide
and has a green background.
And so the main UI thread is only responsible for drawing
the results of these commands, not doing the logic of figuring
everything else out that's happening in your JavaScript on another thread.
So you're utilizing more cores of the device.
And you can sometimes get more performant behavior.
Not always.
Sometimes you can write slow JS, and then that hold things up.
But in theory, you can actually make this more performant
than most traditional native apps.
So just to talk more about what this is-- why is it called React Native?
And the answer is because it uses React, which is this thing that
was developed for the web, actually.
And it's a JavaScript library that I'll talk a little bit about, just
to give you a sense of what this is.
So this is what React code looks like.
If you're familiar with HTML or XML, it looks a lot like that.
You can see there's these angle brackets.
And then there's the slash in closing tags.
And basically, every time you're doing that, that's a component.
And the most basic building block of React Native components is views.
So you can see this example code has a ton of them.
But then you can also build your own on top of that.
So this ReadMore component here, this BoldText component here--
those are built by developers or users.
And then you can kind of layer these abstractions on top of each other.
And the ideas behind React are that, basically, components
should be sort of coherent and composable and reusable.
So if someone builds a React component, you
should be able to sort of stick it in your app,
and it should behave and look and feel the same way as it
was when they originally built it.
So the really nice thing about that is that this maps really well to the way
that people think about applications as they build them.
If I handed you an app on my phone-- say, iMessage-- and said,
can you describe to me what you see here?
You would probably say, oh, well, I see one message that's
a blue bubble coming in from the left.
And then it has some text inside it.
And then I see a white bubble coming in from the right.
And then it has some other text in it.
And each of those layers of the things you're describing
would basically be React components inside a React native app.
And so there's something that's just very intuitive about building
in this way, where there's this analogy between the way
that you think about them as a human being and the way
that you're writing the code.
The cool thing about React, though, is that if you
look at this thing here-- every React component,
the most important method on a React component class is the render method.
And what that is is basically, it's a function
that describes given a state and some properties,
how do I draw this on the screen?
And it's really important that it's a function.
And so it means that when you write this render function,
you write it in a way that is general for every possible state
of the component.
So that means that if the state changes, you still
know how to draw it from scratch.
And so no matter what state the component is, you can always redraw it.
I think I got a little lost there, but let
me use an analogy to help with this.
So the original place that this idea came from was, I think, in graphics.
So this is how video games evolved.
This is a really early video game called Nibbles, where there's basically
a snake that you control with the arrow keys and move it around the screen.
And it picks up numbers, and it gets longer.
And so the snake is really easy to animate because every time it
moves, the head is just-- you draw one more dot on the screen,
and then you just erase the tail.
So it's pretty easy to do this manually.
You just keep track of all the places where the snake is,
and then you just add a new one where he's going.
And then your erase the last where he's gone.
And so writing games like this was really
easy to do in pretty much any way.
Kids could figure it out.
But then this is a modern video game.
I think is Uncharted 4.
And it's really hard.
Here, you can sort of break down, oh, I can see how I might draw this snake.
There's so many things going on here, it's
totally unreasonable to even figure out how you would draw this on the screen.
And then if you think about modern video games, probably
what's going to happen in the next second in this game
is the camera's going to swing around here,
and we're going to be looking at this from a totally different angle.
And almost every pixel on this screen is going to be a different color.
So the only reasonable way to approach this is to say,
hey, I need to have some sort of abstract state of the world,
that I know that this character is here, and his arm is out.
And his other arm is back.
And his knees are like this.
And this other character is here.
And there's also a building here.
And that's made up of these blocks of wood.
And so then you have this abstract state of what's going on in the world.
And then you sort of have a library that says, OK, stick the camera here.
And then draw everything and render it.
And so then the system figures out how to create
each pixel based on what's going on in the world
and where you stuck the camera.
React is basically that for apps.
So the idea is that these things are coherent,
and they map to the way you think about things.
And they're reusable and composable.
And so you can build up these libraries of React components.
So that was this thing that was released in about 2011
and has gotten really, really popular on the web.
But now, it's starting to be popular for native.
Cool.
So React Native is really great because you can take all these great things
about React, and you can solve a bunch of the problem
that we had developing mobile apps.
But one challenge now is that in some ways,
now we went from having to know how to do iOS and Android to now having
to know Swift on iOS or Objective-C, and then Java on Android,
and then also JavaScript.
And so now it's like we've gone from having
to know two things to three things.
And that's just sort of harder.
And then a bunch of the other things that
are annoying about the native development cycle also
apply, like submitting to the App Store takes a long time,
and you have to compile still, some of the time,
if you're changing your native code or anything like that.
So I started working with a few people on this project called Exponent
that is basically trying to solve that and make it as easy as possible
to do what you want to do.
So the idea is write cross-platform apps writing just React Native JS
and not worrying at all about the native code.
So Exponent basically takes care of all the native code
and lets you write just JavaScript when you're building your app.
So we include components that do all the common things that people
want to do in native apps, like Facebook login, maps, camera, camera roll,
contacts, et cetera.
And you don't need to use Xcode or Android Studio.
You don't need to learn Objective-C or Swift.
You don't need to learn Java.
All you have to do is worry about the JavaScript.
The other thing that's really cool that you get when you do this
is that you can deploy updates to your app on the fly, over the air.
Since it's all just JavaScript and since Exponent takes care of the binary code,
you can actually have the same app sitting on your phone,
but then it can download new JavaScript and completely change its behavior.
So you can fix bugs.
You can run a sale in the morning and put a dialog that said, sale, 10% off.
And then you could take it down at night just
by deploying new stuff over the air.
So I'm going to show you how to use Exponent a little bit,
if you ever wanted to use that for a project.
So our website is getexponent.com.
And then you can download two things from there.
There's a piece of desktop software called XDE that I'll demo for you.
And then on your phone, you can also get iOS and Android apps
that you'll use to open your projects.
So if I go to getexponent.com, then go to Installation.
I could download for Mac here.
Actually, I've got it on my computer already.
This is like a cooking show.
So I'll go here and make a new project.
You can choose between tab navigation and blank.
And we might add more templates later.
If you're starting off, I would actually choose the tab navigation thing
because it gives you lots of different things.
And I always find that it's easier to delete stuff and change stuff
than it is to write stuff from scratch.
So I kind of like to start with the tab navigation project.
I'll just call it CS50 demo, and I'll make a new project.
And it'll start up your project and start showing you logs.
And I can open it in my text editor.
After a second, it will say, product is open.
You can now use the send link to device buttons for your project.
So what you see here is there's a URL here,
which is like the URL for your project.
And the way to think of this is sort of like web development,
if you're familiar with that, and that when
you're developing a website, if you have the URL for it, you can just go to that
and open it, and then see what you're working on.
And that's the way it works with Exponent, too,
except that instead of opening it with a web browser,
you open it with the Exponent developer app.
So I can either send that to my phone using Send Link or I can just open it
in the iOS simulator, which I'll do here because it's easier to see.
So then it takes a second the first time.
But then it'll open it up in the simulator here.
Usually it doesn't take this long.
I'm not sure why it's so slow today.
AUDIENCE: Hey, Charlie?
CHARLIE CHEEVERS: Yeah.
AUDIENCE: While this is loading, can you show us that a little bigger?
CHARLIE CHEEVERS: Which ones?
AUDIENCE: Just the relevant ones.
CHARLIE CHEEVERS: This one?
Well, I don't know why it took so long.
But anyway, you get this thing.
It says here, welcome to Exponent.
Change this text and your app will automatically reload.
So I can go into my text editor, and then
find where it says "change this text and your app will automatically reload."
And I can say, hello, CS50!
Sorry that took so long to load.
Save it, and then-- oh, that was a lot faster.
Just a second later, it appears.
So you can see that this is sort of one of the basic building blocks of React
Native, is these text elements.
They're pretty simple.
They're just like a HTML tag, pretty much.
But you just say Text, and then you can include text inside it.
The other really basic building block that I'll show you is just views.
So I can wrap this text inside a view.
And a view is sort of like a div on the web.
It's just a rectangle that you can decorate.
And the way you decorate stuff in React Native is with this style attribute.
So just so that this will show up, I'll give it a border.
I'll give it some rounded corners, and I'll make it really thick
so it shows up.
And I'll make it red so it's noticeable.
And I'll make it solid so that it shows up.
And I can give it a width and a height.
And now, I have a big red border with rounded colors.
And then I can also set background color and things like that.
You can use hex colors.
Another thing that's cool is-- so on the web,
you typically use CSS, which is sort of its own separate DSL,
whereas in React Native, all the styling is just done using JavaScript objects.
So that means that this is just a regular JavaScript object here.
And that means I can do math here.
So I could do 100 plus 100 plus 50 here instead.
Save it, and that'll get a little bit skinnier
because that's 250 instead of 300.
But this means that you can use variables.
You can say something should be one third the width of something else,
et cetera, et cetera, et cetera, which is pretty hard to do in CSS
but is really easy to do in React Native.
And so you can see here that most of the time,
as people write more advanced code bases,
they tend to use variables for their styles so it's more readable.
And so you can just assign styles.codeHighlightContainer
and include that here.
You don't have to inline everything the way I have here.
Cool.
So this is how you basically build really simple stuff using Exponent.
I can then share it to my phone, if I want, if I hit this Send Link button.
I put in my phone number here.
That will send a text to my phone.
And then I guess it'll be hard to see on camera.
But if you open that link on your phone and you have the Exponent app
on your device, then it will take a second
to load-- probably not as long as it did the first time--
and then it will show up on your device, as well.
So you can immediately start sending to-- if you're working with a partner,
you can send your work to your partner, or you can open it yourself
on your iPhone or your Android phone.
And so then that's the basic workflow.
So I thought that what would make sense is
I could show you guys how to make a really simple hangman game.
I think there's a lot there.
So what I think I'll try to do is just give you an overview of hey,
here are some things that are possible and a really brief coverage
of how to do it.
But it'll probably be just enough so that you
could know that something is possible and start googling it.
But you probably wouldn't be able to remember it from this seminar.
So I decided we'd make a hangman game that looks kind of like this.
Really simple.
We'll just have a keyboard down here.
We'll have to make a fake keyboard because we want to disable the letters
and numbers as we play them.
And then in the middle, we'll have a hangman that gets progressively drawn
as you guess letters wrong.
And then above that, we'll have the words to guess.
I also decided that I would pull the words to guess
from things that are trending Google searches so
that it would be interesting.
So I made this.
I was working on this last night.
I put the source code up on GitHub up so you can download the whole source
and play with it yourself.
And if you have the Exponent developer app on your phone,
if you go to that URL, you'll just be able to open it up and try it
on your phone.
So the first thing that I thought I would cover
is-- well, let me open up the project in Exponent here.
So let's open it up in the simulator so we can see what's going on.
So first thing it says is, loading a trending phrase for you to guess.
It loads that over the internet, and then gives
some sort of trending phrase.
Oh, Chicago Bulls.
So I got that one wrong.
But I just wanted to give you a demo of what we're trying to build.
So the first thing we'll focus on is how did we get that trending topic
from the internet?
And here's the code for that.
So you can see here, this getTrendsAsync.
This is an async function.
If you haven't written modern JavaScript,
one of the best things that's true about very modern JavaScript
is these async and await keywords.
And they basically let you do these things-- like make network
requests-- that take a long time to do.
And you can sort of say, hey, go do this,
but then continue running the code within my program.
And then when it's done, re-enter right here.
So I'm going to do that here, where I fetch from this endpoint
that I've set up that serves me just a JSON
string of the trending topics from Google.
And you can use fetch, which is a browser API, actually.
But it's been implemented in React Native and is built in by default.
So whenever you want to make network requests-- basically,
HTTP requests-- you just want to use fetch.
There's tons of documentation on it since it's built into browsers.
And so it's pretty easy to look up how to do POSTs and add parameters
and how to set headers and all those other kind of things.
But we're just doing a simple GET from a URL.
And so we don't actually need any of the other options except the URL.
And then the await means that other code will run while we're
waiting for the network request.
But then it will assign the response value to the response.
So it's really simple.
It's just regular JavaScript.
The other thing that's pretty cool about this is you noticed at the top here,
I do this import diacritics from diacritics.
What I'm doing there is using a diacritics module
that someone else made.
You can use any JavaScript that's on npm inside of React Native.
Some things rely on node APIs and won't work.
And some things rely on native code, and they won't work.
But most things that are just random JavaScript
will work just fine within a React Native project.
So what diacritics are are like if there's an accent on an E
or an umlaut over a U, that would break our hangman game
because there's no u with an umlaut over it on our keyboard.
So we need to turn that into a regular U.
So what I could do is research all about this stuff
and write a regular expression myself of how to strip it out.
But I would probably miss some edge case or not
do it in an efficient way or something like that.
But what I was able to do instead was just Google for npm diacritic strip.
And I found a Stack Overflow question about it.
And that looks gross.
But then somehow, I found this module on npm
called diacritics that will let yous strip them out.
And it had a really simple example here.
So then if you want to use that in your project, all you have to do
is go into your project directory and run npm install diacritics.
And then this will basically download from npm
and let you use this, whoever made this code.
You can use it inside your application.
And so people share a lot more stuff in this JavaScript ecosystem
than they do in the native code world.
So then the next thing that I wanted to focus on was this thing, Redux.
What Redux is is a way to basically manage the state of your application
and pass it in to React.
You don't need to use it to build simple UIs.
But as you start having a complicated state in your application,
you pretty much need it.
And there's basically three concepts involved
in it-- state, actions, and a reducer.
The most important of these is the reducer.
And what that basically does is it's just one
function that takes your state and some action and returns a new state.
That was all really abstract, so let me show you what that means in practice.
Here's the hangman app.
And so here's my reducer.
So it's just one function that takes a state and an action,
and it ends up returning a state, which is the new state of the game.
And what state means-- I think the easiest way for me
to think about it is if you were going to implement a save game function,
state is everything that would have to be written out to disk
to save the game.
So it's everything that's going on in a meaningful, abstract way--
in the case of this game, the set of letters that you've already guessed,
what the word is, and how many strikes against you you have,
how many limbs on the hangman, and then this thing
called game state, which is like the game hasn't started yet,
or you won, or you lost, or it's in progress.
And if you have all those pieces of information,
that's kind of enough to recreate the game in its entirety.
So this one function just takes initial state and action and returns that.
And so it basically does different things depending on what the action is.
Actions have a type.
So if you guess a letter, then it makes sure that the game is in progress.
And then if you've already guessed that letter,
it just says, you already played that letter.
Otherwise, it adds another letter to the list of letters you've played,
and then adds that letter to the guessed letter C,
and then checks to see if that letter's in the word,
and then checks to see if you guessed all letters in the word.
And so basically, this is where all the game logic
is and the meat of your application.
It's in this reducer.
And if you write your apps this way, it seems more complicated at first,
but they end up being very clean and very easy to get bugs out of because
at any given moment, all you have to reason about is OK,
what's the current state of things?
And then how do I get to the next state of things given an action?
And so then I think my main piece of advice
here is just if you build anything complicated with React Native, just
google Redux and read the tutorial and use it.
This is probably too abstract for you to actually understand
what I'm talking about right now.
But I would use it.
So next thing I want to do is talk a little bit about making the keyboard.
So the keyboard, if you look at it, it's basically just a bunch
of letters and numbers inside of boxes.
And so it's pretty easy for us to make this fake keyboard
just by using views for the boxes around the letters and numbers
and texts inside of those.
So if I look at this keyboard thing, you can
see that it's just a React component.
And the meat of it is basically that if the tile is active,
then I have a letter tile.
And I wrap it in a touchable bounce, which means that you can touch it
and that it'll bounce when you touch it.
And if it's not active, it doesn't have it wrapped in a touchable bounce,
and it looks different.
So one cool thing about this is just the idea
that you can just wrap things inside of something like touchable bounce,
and they'll do what you expect-- they'll bounce when you touch them,
and then they'll call whatever's in the onPress attribute when you press them.
There's also touchable opacity and touchable
highlight, which have slightly different effects on the things that you touch.
But you can use those around any view or any text
or any image or anything like that.
And so then, to draw the letter tiles, I just
use the same styling that I was showing you.
It's very similar to CSS styling except that it's JavaScript objects.
But all of these things are essentially similar to CSS properties.
And so you can see that basically, if it's active,
I use slightly different colors than if it's not active.
And that's how you get sort of the effect of things looking
faded when they're not active anymore.
And so then, the most interesting part of this maybe is you can see here,
there's actually different numbers of characters
in each of these rows on the keyboard.
There's 10 numbers at the top.
But then at the bottom row, there's only 7 letters there.
And so it would be really gnarly if I had
to do the math to figure out how to space all these things out, especially
since I want this to work in general, across all different screen sizes.
I want this to work on an iPhone 5 and then also an iPhone 7
and also my Samsung Galaxy Note 7 that hasn't caught on fire yet.
And I don't want to have to write different arithmetic for all those.
And so one thing that's really cool is that React Native uses
Flexbox as its built-in layout engine.
And so Flexbox is this thing that was added to CSS recently.
And so you can just Google it and find out all the things that it does.
I spend a lot of time in my life visiting this page over and over again
to see all the different things it can do.
And in this case, the most important line
here is this thing that's justifyContent space-around.
And I can see when I go look through all these things,
here's the justifyContent attribute.
And you can see the different options that it gives you.
There's a way to squeeze everything at the beginning of your view, a way
to squeeze everything at the end, a way to center it.
And then there's these more interesting options,
space-between and space-around.
space-between will put even spacing between all the things
in the view but nothing on the edges.
And then space-around will put even spaces between stuff and at the edges.
And so space-around is kind of intuitively
what we want for this keyboard.
And so I use it here in the code.
And just by adding this one line of code, the keyboard looks like that.
But then you can see, I could change this.
We could make it look like this if we do flex-end.
So if I just do flex-end, then this will reload.
And now all the keys are squeezed over to the right side of the screen.
So it's pretty easy to just make these changes very, very quickly
without doing a lot of gnarly arithmetic and math or anything like that.
And so then I wanted to show you drawing the hangman because I just showed you
how to do text.
And I showed you how to do rectangles.
But if I guess letters wrong here, it draws a circle, and then
a line, and then a diagonal line.
And those would be hard to do with views and text.
But when you want to do anything like this,
there's something built in called SVG, which
is very similar to the SVG on the web.
And so the code for that just looks like this, where you have an SVG component.
You give it a height and a width.
And then what this line does is it basically says, show this part
if there's more than one strike against me.
And so in this case, it draws the head.
And so there's just a circle component, and you give it an x and a y
and a radius, and then some information about the stroke,
which is like-- stroke is like a line in drawing.
And so I just add in all these SVG parts.
If you google like SVG spec, you can find
all the different things you can do.
But the most simple things you can do are just
drawing circles and lines and boxes.
And hangman is really simple, so I end up only using circles and lines here.
And so then that's how I'm able to draw this.
And then if I win or lose the game-- Vine shut down,
I guess-- you can see I have this sort of sticker
with this military-looking font on it, which doesn't come with iOS or Android.
So I actually had to use a custom font for this.
And the way you do that is pretty simple.
In your project directory, just somewhere there,
you put your font file-- in this case, that's a font called top secret.
I just found it on the internet on a font site.
And then in your code-- especially if you
start with the tab project in Exponent, we give you a bunch of basic code
for doing this.
You just write require and then the path to that asset.
And what Exponent will do is upload all your assets to a CDN,
and then serve them to the app when the app needs them.
So you can swap in fonts, images, whatever
without having to update your app in the App Store.
So I just wanted to give you an example of using a custom font.
So then if we put together all these pieces and we have our game
and we want to publish it-- let's say I decided I did
want to squeeze all the keys to the right of the screen like this.
And I want to make that the version that is sort
of the official, canonical version.
All I have to do is hit the Publish button here.
And this will basically take my code, which is currently
being served from my computer, and it'll package it all up
and put it on Amazon's web servers in the cloud
so that anyone who hits the URL that I gave you
earlier-- exp.host/@ccheever/hangman-- will then get this new code when
they visit it on the developer app.
And then if I wanted to, I could run one command at the command line-- xbuild
ios-- and it will actually build an iOS app
that I can submit to the iOS App Store.
Or I could run xbuild-- oh, I guess I need to set some settings.
There's documentation on it.
But basically, with one command, I can build an iOS app
that I can submit to the App Store, or I can run xbuild android
and build an Android app that I can submit to the App Store.
And what that will do is give me an app that's basically the Exponent developer
app, except that all the branding is switched to the branding for your app.
And the name is switched to the name for your app.
And it's only pointed at the URL of your published project
so that a user would never know that it's using any of this stuff.
They'll just see it as a regular app.
But anytime you want to make changes to it, you just hit the Publish button,
and they'll get the new code the next time they open the app.
So the main point, I guess, is just by writing a bunch of JavaScript,
you can make something that behaves and looks
and feels like a really native app.
And you can put it in the app stores.
But you can get most of the benefits of web development, where you can just
pass around a URL while you're doing development,
and you can just change stuff and see the changes happen on the fly.
Cool.
I just wanted to give you guys an overview of a possibility,
if you wanted to use that for your final projects.
Cool.
Thanks for having me.
[APPLAUSE]
DAVID J. MALAN: Questions for Charlie?
CHARLIE CHEEVERS: Yeah.
AUDIENCE: So you're not really coding on any platform on Exponent.
You're coding on some other thing and transferring the code?
Or where are you-- I saw Atom, and I saw--
CHARLIE CHEEVERS: Oh, yeah.
OK.
AUDIENCE: What's going on?
CHARLIE CHEEVERS: So you can use your own text editor.
You can use Atom, you can use Vim, you can use Emacs, whatever.
And they're just text files.
What's going on is with XTE, it runs this thing
called the React Native Packager, which is this process that
goes through and scans all of your JavaScript files,
and then transpiles them into a version of JavaScript-- there's
a lot of fancy, modern JavaScript, like the async,
await keywords that I was showing you and things like that.
And so to have it run on all phones, that has to be transpiled down to ES5.
Transpilation is just like turning newfangled stuff
into equivalent old stuff.
And so it bundles it all up into one file
so that it can be transferred over.
The reason that it took so long to load the first time
was it was scanning all the different files
and then transponding all of them, and then packaging them
all up into one thing.
It's pretty smart, though.
And so when you make small changes later on,
it doesn't have to do all that work all over again.
It just only does that one file.
And so then when you're doing development, it runs a web server
and basically will serve up the bundle so that the client app on your phone
or on the simulator can just load that by making a web request to that web
server.
And so then when you do publish, it copies all the code into the cloud.
And so then instead of requesting from the web server running on your machine,
it just requests it from the cloud.
Does that make sense?
AUDIENCE: Yeah.
CHARLIE CHEEVERS: OK.
AUDIENCE: It's a little advanced for me, but I'll get it.
CHARLIE CHEEVERS: Sorry.
Yeah.
AUDIENCE: So why did you guys choose JavaScript?
Is that the iPhone or--
CHARLIE CHEEVERS: There's basically one really big reason, which
is that Apple's developer terms of service
say you can't download any code from the internet and run it on the iPhone
or you'll get banned from the App Store unless that's
JavaScript code running on JavaScriptCore,
which is their JavaScript interpreter.
And so anyone who wants to do this downloading
new versions of the app on the fly over the internet,
you have to do it this way using JavaScript.
You could do kind of crazy things where you translated Python
into JavaScript or something like that.
But it's easier to just use JavaScript.
Yeah?
AUDIENCE: So if you want to use some kind of API that
is for Android or for Right how do you use it?
CHARLIE CHEEVERS: So if you wanted to do some low-level thing-- basically,
Exponent is where you just write just JavaScript.
You could take all this JavaScript and set up a new Xcode or Android Studio
project and then write the native code and integrate it there.
If you Google React Native native modules--
I could talk for, like, two hours about the details of that.
But there's ways to write native code that way.
And you could use your same code from this
if you needed to dive down and write your own sort of specialized
platform-specific stuff.
You also can do stuff though where you can customize per platform.
If you just wanted to say, hey, I know there's a Back button on Android.
And so I want to handle that a little differently.
Or I want to be able to say, hey, you're an Android to certain people.
There's these variables called platform.ios in there.
That's iOS or Android, or maybe in the future, Windows Phone
or something like that.
AUDIENCE: And it will enable Siri or Apple Pay or something like that.
CHARLIE CHEEVERS: Yeah.
So we have a bunch of those libraries built in.
And so you could integrate with those that way.
And they might only work on one platform.
But you could check to see if you're on that platform.
AUDIENCE: When you're hot reloading, does
that reload the module or the whole package?
CHARLIE CHEEVERS: You can turn on and off live reloading and hot reloading.
If you're in the iOS similar, you hit Command-D to bring it up.
You can't have them both on.
This is like a weird gotcha of React Native
that somebody will fix in the next couple months, I'm sure, but isn't yet.
But you can't have live reloading and hot reloading on at the same time.
Live reloading means that whenever you make a change,
the whole app will reload.
And hot reloading means that it will just reload that module.
Hot reloading is cooler and faster, but it doesn't work all the time.
And so I think most people end up using the live reloading when
they're doing most stuff.
But if they are just going to tweak a color or tweak moving some stuff around
or changing some text, they might turn on hot reloading for a little while
because that iteration cycle is so fast.
And if you're just doing something not too complicated, it's pretty reliable.
But if you ever start changing the logic in your app or something
deeper or more complicated, the hot reloading thing is little unreliable.
AUDIENCE: Can this do more complicated things, like maybe a 3D game?
CHARLIE CHEEVERS: Yeah.
But we're actually releasing that, like, next week or maybe the week after.
No promises.
But somebody made a game.
I can show you a 2D game that somebody made if you're interested.
Actually, it'll take a little while.
So I probably shouldn't show you now.
But yeah, people have made games with this.
But I would say that if you wanted to make a 3D game today,
you probably shouldn't use this.
But follow our Twitter, and we'll announce this stuff next week.
And then if you were interested in just different examples,
there's this awesome Exponent repo that just
has a readme with a bunch of examples to check out and copy and things to read
and stuff like that.
And then we have a Slack that has a community where lots of our users
will help each other with questions and explain how to do different things.
And then the docs are at docs.getexponent.com.
So we're happy to help anyone, too, if you join our Slack community.
I know this probably wasn't enough information
to actually go off and complete a full project without learning more.
But we have a pretty helpful community.
AUDIENCE: So what would prevent a malicious developer
from creating an app, and then later on update the app on the fly?
Do you have a mechanism in place to prevent this kind of problem
from occurring?
I'm just wondering from a local device security perspective,
how would it know the user of the app?
CHARLIE CHEEVERS: So Apple would just ban that.
They've moved away from a purely technical approach
to enforcing security that way to one that basically,
if you were to change an app that was finding changing stations for babies
into some sort of porn app, they would just say, you can't do that.
You're done.
But you could do it for probably five minutes before they
caught on or something like that.
And then within the Exponent developer app and stuff like that,
you basically have to trust people.
It's a developer app, so you just load code
you trust and don't load random strangers that you
think might be doing malicious things.
DAVID J. MALAN: Thank you so much, Charlie, for joining us.
CHARLIE CHEEVERS: OK.
Thanks for having me.
[APPLAUSE]