MONICA DINOSAURESCU:
Good morning, everybody. Thank you for coming. Thank you for coming
to this 9:00 AM session for the jetlag and
insomniacs, and those of you haven't left from
the party last night. So let's talk about
web components. We had a whole bunch of
titles for this talk. It doesn't actually match
what's in the program. My favorite was The
Meownica School for Kids who want to Web Component good,
and do other Things Good too. It was rejected. And addyosmani suggested,
Meow Meow Protips Meow Meow, which is pretty much
what's going to happen here. So meow meow. Hi, everyone. I'm Monica. I'm notwaldorf on Twitter and
GitHub and internet places. And officially at
Google, I'm an emojineer. And that's because I get
very excited about emoji. And I sort of like
shout about it into the void that is Twitter. But what they actually pay
me for it is to-- oh-- emoji. So the funny thing
about this slide, I had to use android emoji
and not the Apple ones. It was mandated by legal. And what I do is web components. And for the four
people in the audience, I think-- as we did
a raise of hands, who don't know what
that is-- web components are a standard we've
been working on. So that you can write
reusable widgets for the web. So you can make your own fancy
button, and give it to people, and everybody can use it. I work on Polymer, which
is a library that helps you write these web components. And in particular, I write
web components with Polymer. We have elements like these
ones that are like material design [INAUDIBLE] elements. We also have elements that
don't look like anything. We have a declarative
AJAX element that you can put in your
page, and get super easy XHR requests. And that's kind of fun. So, you might not
think of yourself as an element developer. You might think you're
a web developer. You make apps. But if you want to start
playing with web components, I think thinking like an element
developer is really important. So you might only make elements
for your own application. But you're kind of
making them for future you, because future you is going
to have to use these elements. And if they're
crappy, future you is going to have a hard time. So, I'm going to tell you
basically all the mistakes I've made in the last year
of making web components. So that maybe you won't
have to do the same ones. So there's like
four things that I thought are kind of interesting
about making web components. You've got to make an API that
doesn't enrage your users. And this is actually
kind of interesting. You've got to
maintain this element, once you start giving
it out to people. You've got to make
sure that it's fast, and isn't
slow like molasses and destroys
everybody's application. And you want to make sure
that it's accessible. So these are the four things
we're going to talk about. So let me tell you a story. In the '90s, we had HTML1. And it was lovely. And it was basically
like reading the paper on the internet. Things that you might see on
a page, or things like links and headers and images if you
were lucky, and that's all that happened. You opened the web
page, and you read it, and that was pretty much it. And in 1995, things
got exciting. We got HTML2. And in HTML2 we got
three awesome elements. We got input. We got form. And we got select. And I think we button,
well input type equals button was there. So now this meant that websites
could offer you interaction. You can type something
in a text box. And the website would
react to you in some way. And the reason why I
think this is important is that these are basically
like OG web components. They are little,
reusable widgets that the platform
gives you, and you can put in your application. That's exactly what
a web component is. And since '95, in the 21
years that we've had this, we've come up with a couple
of more web components, or like whatever you
want to call them. We have video and audio,
which are kind of awesome. Canvas is like an enormous
framework in and of itself. Dialog and details
and things like that, aren't really implemented
in all the browsers. And a lot of the input
types aren't implemented in all the browsers. So the reason why
I'm telling you is that, even though
we kind of had web components for
something like 21 years, we're not very good at
making web components. And I'm going to spend the
next 10 minutes telling you how input is really terrible. Because that's one of my
favorite things to do in life. On the other side of
the world, we have UNIX. And here's where it begins to
be a little bit of a flame war. So we've had UNIX
since the 1970s. And one of the things that
UNIX is really good at is making reusable
little programs that everybody knows how to use. These are the ones
that I've just used probably in the last week. These are the ones
you've probably used ever in your life, maybe
not telnet and links, unless you were playing
a joke on somebody. But UNIX is really good at this. You use ls every day. If you use a terminal,
you use ls every day. And the reason why
UNIX is so good at it is because UNIX has a
philosophy about how to write these super tiny
components, commands, programs; whatever you want to call them. And that's what we're going to
talk about for a little bit. Because if you're going to go
ahead and write web components, I want you to think of what grep
does, and not what input does. Grep is a great example
of a reusable component. Input is absolutely terrible. First thing, so UNIX has 17
bullets in their philosophy. And some of theirs
are super meta, like value developers time
over computers, which is great. And I don't know
what that means. But one of ones that's
the most popular one is that your component
should do one thing. And this is 100% true
of web components. If you build a component,
it should be really tiny. It should do the thing
that it says it does. And it shouldn't
do anything else. If you look at the
cat command, cat takes a file from your
computer and spits it out to the terminal. It doesn't try to print it. That's what lpr is there for. It isn't trying to
find a string in it. That's what grep is there for. It doesn't try to sort
it alphabetically. That's what sort is there for. Cat takes a file, and
prints it to the terminal. Input, on the other hand,
has something like 21 types, I think, today last
time I checked. Even when it started in 1995,
it had 8 types, off the bat. That's how we started the races. And that's really terrible. Because they don't really
have anything in common, these input types,
other than the allow you to select a value. You have input type equals text,
where you just mash keyboards, and they appear on screen. You have the slider,
which you drag a ball on a vertical slider. And that magically
picks a number. You have a color picker
that gives you an RGB color. You have the map type, which
is basically like an image map. And where you
click on that image is the thing that
gets saved as a value. So again, all of
these things they have in common the fact
that they have a value. They shouldn't be
the same element. They don't even look the same. And then you start painting
yourself into a corner once this is your API
that you start with. So here, I am creating input. It's by default of
type equals text. So it's an HTML input. And because you can type
in, and it has a caret, you can get where that caret is. And selectionStart is the
property that you do this. And then I'm going to change
the type to input type equals number. I can still type. I still have a caret. But now, if I actually try
to access that property, I get an exception. It's not that it's a bad value. I literally get an exception. The browser panics. And this makes no sense
from an API perspective. Both of these are an
HTML input element. Both of these have
the same prototype. They have the same property. And yet, if you access it
on some types, like most of the types to be honest,
selectionStart just barfs on your console. And the reason why
this is happening is because input type
equals text and input type equals number should never
have been the same element. They were the same
element, because in 1995 we didn't have JavaScript. We didn't have polyfills. We didn't know how to fall
back to a default behavior. So we're just like, we're
going to put everything in one element that is going
to have a default value. And it's going to be great. But 21 years later, we're
still paying for these mistakes that we had to do
in 1995, because of what the platform was like. So this is why don't look
at input for API advice. Because input makes
mistakes all the time. Another one of the UNIX
philosophies is composition. Programs play very nicely
with other programs. In UNIX this happens with pipes. The output of any
program can become the input of any program. And everything works
magically and beautifully. And the way this
works on the web is by sort of nesting
elements together. So select is composable. Select and option
are composable. That's how you can put
elements in a checkbox. And you can put in text. And you can put in a button. And you can put in an
input, and an image. And what do you think
is going to happen here? Does anybody know
what actually happens? Yeah. This happens. It's amazing. So the input gets rendered
outside of the select box. We're not even trying. There's no image. And with a button, we're
just taking its text value. This is not a
composable element. This looks like it
could be composable. And select had a chance
to get it really right, and they made a mess of it. And the historical
reasons here are again, because in 1995 when it
came out, IE4 on Windows didn't know how to draw
select combo boxes otherwise. But 21 years later,
again, we can do better. And with Polymer,
we did do better. We made our own select box. We called it paper, because
it's material design. And in the dropdown,
you can put on items. So you can put in text. And you can put it an input. And you can put in a button. And it looks like exactly
what you would expect. There is the text. There is the button. There is the lemon. I don't know why you would
put an input in a pop-up menu. But I mean you could. Nobody's stopping you
if you want to do that. And that's a composable element. So when you're making your
elements, think about this. Are you expecting to have
children composed in there? And if you do, try not to
make assumptions about them. Try to expect sort of
any types in there. Because people are
going to put inputs in your dropdown
menus and you're going to have to deal with it. And this really leads me
to the extensibility, which is the code that you're
writing today should work in 10 years from now. ls was
written 40 years ago on a platform that is
nothing like the Mac that I'm running it now. And ls still works. It probably had
to be recompiled. But I don't think anybody
changed the source code dramatically. 20 years ago we wrote form. And form is the opposite
of an extensible and planned for
the future element, because form only works
with the input element. When I say it only
works with the input, I mean it is literally
baked in the parser. When the parser gets
to the form element, it only looks for elements that
have the tag input and skips everything else. And this blows for
us as web developers. Because what if I make a
super awesome input now that is way prettier than
the crazy native input? I can't put it in a form. Because the form is going
to ignore it altogether. So I have to start
hacking around it, and make hidden input, so
that the form recognizes it. So in contrast, in Polymer we
try to not make assumptions about what sort of things,
again, our element expects. We have the swipeable
container, where anything that you put in it,
gets this magical android swipe left or swipe right action. And this means that I can put in
divs, and I can put in inputs, and I can put in
Polymer elements. And I can even put
in web components that people wrote
without Polymer. That element doesn't care. It accepts everything. And that's a really
good element. Because if it works
today, it's going to work in the same way like
in 10 years, when the DOM might change a little bit. But the elements stay similar. So the point here is to not
make any assumptions when you're making your elements. And so the way I interpret
it is that when you create your element, assume that
it starts sort of naked, without anything. It doesn't have any
properties set on it. It doesn't have any children. It's just like born
into the world. And then it starts
reacting to things. When properties
change, react to that. Don't assume that the
properties are already set. If people add content
to it, react to that. Assume that when your element
starts up, it has nothing. And you have to deal with
everything that follows. And that means that
pretty much in any way that people are going
to use your element, you're going to be fine. Because you've pretty much
covered all your bases by just reacting to changes. And this also leads me to
this conversation about state. Because unlike UNIX-- and
this is where UNIX wins-- UNIX programs don't
really have any state. They start up. You give them some input. They do something
with the input. And then they die. And everybody is happy. But on the web, the input lives
there on the page for as long as that page is open. And you're probably
going to type in it. And it has to somehow
remember what you typed in it. And that is in its
internal state. Which isn't necessarily bad. But what you should
do about it, is that make sure that if
your element changes the state internally,
you communicate this to anybody who cares. You fire an event every time
this internal state changes. And similarly, you
as a user should be able to always change the
internal state of this element, in the same way that
the element can do it. And guess what. Guess what input fails at. So input type equals
number is a good element. Because in theory, it lets you
validate what you type in it. So it lets you type in digits
and a period for decimals, and the negative sign,
and E for exponents. So it doesn't let me
type in Monica or emoji, which is great I guess. So if I type in 1234, the
internal value of the input is 1234. If I type in nothing,
the value is nothing. And if I type in junk, the
values nothing-- wait, what? Yeah, so it turns out because
this value is actually invalid, the input is going
to secretly reset the value to the empty string,
but not actually tell anyone. It's just going to do
it internally, and not fire an event about it. And if you start with
nothing and you type in junk, you as a programmer
cannot detect this change. Nobody has told you that
anything has happened. But you with the eyeballs,
are looking at that input, and be like, look
there is junk in it. You've got to do
something about it. But as a programmer, you can't. Because input is like hiding
its state away from you. So don't do that. Don't be input. Which is pretty much the point
of this talk, never be input. Because nobody really
likes surprises. Surprises in an
API are the worst. They're like finding that
your cake is made out of kale and not cake. This is San Francisco, where
everything is made up of kale. This is the new
tragedy in my life. So remember how I said that the
reason why we painted ourselves into a corner with input
is because in 1995 we didn't have polyfills. We had to somehow
have a default type on all these stupid inputs. And the only way we
could do it is just jamming them into an object. But now we have polyfills. So we need to deal
with polyfills. And the really important
thing about polyfills is that if your element
expects a polyfill, please for the love of
God, do not include that polyfill with the element. And here's a story. So we have an element that uses
the web animation polyfill, with the web animation spec,
which works on some browsers, and on all of them. So there's polyfills for this. And we were like, we're going
to be so nice to our users, and include the polyfill
with this element. And everything is
going to be grand. You're going to
have a great time. And then Chrome settings came
around, and they're like, we would really like
to use this element on Chrome settings, a
page that runs on Chrome and no other browsers. Chrome has the web animations
standard implemented. But because we jammed the
polyfill in that element, Chrome has to actually download
the polyfill for something they already know how to
do on every single page. And that's really great. So they don't really
want to use that element. And they hate us for it. So the moment you include
the polyfill in your element, you take that choice away from
the application developer. Maybe they want to use
a different polyfill. Maybe they don't even care about
supporting Internet Explorer. Who cares? Don't jam the polyfill in there. You're not actually
helping anyone. Document it that it's required. But let the user
take care of that. So what I hope you got
from these last 10 minutes is that input is terrible,
and you should not look at it for any API
advice, and that grep is kind of really good. Because UNIX is actually
really good at making this. So if you want to read the 17
bullets of UNIX philosophy, I strongly recommend it. They're kind of
really interesting. And they're probably going
to help you make better APIs. Got it in the end. Awesome. So we have an element. We've given it to people. It has a beautiful API. Nobody hates us for it. And now we actually have
to maintain it somehow. So, the thing about
maintaining your elements and why it's important
is that if you go on npm, and you download a
package that hasn't been updated in two years,
that's going to give you like the creepy jeebies. If nobody cares
about this package, and nobody is
fixing it, then I'm probably going to be
running with a lot of bugs. This is the same
with web components. If you want people
to use your elements, you've got to keep your
elements up to date. Because that makes
them cool and usable. And one way we in Polymer
do this is by making sure that we follow semver. Oh, whoa, whoa, whoa,
whoa, whoa, whoa. That was exciting. We got there, semver. I get excited about
semver all of the time. So semver stands for
semantic versioning. And basically it
means that every one of these numbers
in these versions actually means something. They're not just random. So the last number--
on the right here, I have a tweet
from Dave Methvin, who makes fun of semver. Because no matter what
you think you're shipping, you're actually going
to break your users. So keep that in mind. The last number means that
this patch has a patch fix. It has bug fixes. It's still backwards compatible. Everything is a-OK. The middle one means that
you're shipping some features, but it's still
backwards compatible. So if you're using this version
yesterday, and then you update, and you get the new version,
your app should still be fine. You're going to
get new features. You don't have to use them. But everything
that used to work, should still continue to work. It probably won't. Because you'll write some bugs. But that's a different problem. And the first one
is a major version. This means you're actually
introducing breaking changes. So if somebody wants to
pick up this new version, they actually have to
do a little bit of work for everything to work
in their application. And there's two things
I want to tell you about major version bumps. One of them, numbers
don't have meaning. So please do not think that
increasing your major version is actually a marketing
ploy, or anything like that. Don't get obsessed about this. All you're doing is
communicating that this version has breaking changes. You're going to have
a bit of a hard time. And the second one is just
because you can communicate these breaking
changes, doesn't mean you should have really
aggressive breaking changes. Breaking changes are really
terrible for your users. They have to do work. They have to read the
new API, and figure out how you broke them,
and figure out how to make their stuff work again. So in Polymer we try
to be very deliberate. We haven't shipped
a major change yet. Because we want to make sure
that the moment we ship it, it's a right change and it's
going to not be actually very hard for users to update to it. So be very deliberate
about what you're shipping in a major change. Don't just abuse it, because
you can communicate it. That's what Ruby does. So now that we have semver,
we can tell the users that this version is
going to break you or not. But the only way we're
going to figure out if we're actually going to
break users is by testing. And this should not
be new to anyone. You write software. You test it. Duh. But testing web components
is kind of interesting. Because web components are new. And I found that I had to
test things that I did not expect that I had to test. The first one is
obviously the public API. If you pinkie swear
that a function exists, you should make sure the
function exists and does what it says it should you. Duh. And I'm trying to click now. We're having great
times with this remote. I really like it. So the other thing
is that you might want to start introducing
this idea of a private API. JavaScript doesn't care. So don't worry about that one. But if you introduce
a convention, like underscore
means private, you get to be responsible
for less of that API. A lot of your
configuration methods, or any of your
internal functions, you don't have to
make them public. Because if you're
making them public, you're responsible for them. But if you make them private,
then anybody who is using them, you can be like, listen
you're on your own. I told you not to use it. If you really want
to use it, I can't promise it's going to be there. So in Polymer we
use underscores. Any functions or properties
that start with an underscore, or two underscores if it's
a behavior, are private. Use them at your own cost. I might just delete them
for shits and giggles. You should test
your accessibility. So elements should
be accessible. And I'm going to rail on
this one in about 20 minutes. But you should also test this. You should unit test it. Because you don't
want to break it. We use the accessibility
developer tools. It's on GitHub
under Google Chrome. That's what this
cryptic diagram means. And they're basically
an API that you can run as a unit test. And every time you set something
like roll on an element, it makes sure-- it runs 20 tests
and makes sure all the aria labels are set up
correctly and tab indexes are set up correctly, and
your contrast isn't terrible. So it's really good. You can automate them. You should also test
the look and feel. And this is where
things get interesting. Because your vending elements
that look like something, the thing that they look like
kind of becomes part of it becomes part of your contract
with the element user. So I discovered this
the super hard way, where we had an element. It was a button. And I thought I was
being extremely awesome, and I changed the box-sizing
from content box to border box. And I was like, everybody is
going to love this change. And I broke 15 people. Because it turns out if you
change it to a border box, and somebody was sending
a size on that element, that site is now
completely messed up. And they're going to have
to adjust everything and add 20 pixels to everything. And I shipped that as a bug
fix, and it was actually a breaking change. Go me. And that's because I
didn't any test for the UI. So make sure you
actually test the UI. Because you're
promising your user that a thing looks like the
thing it should look like. Here's a bunch of UI
frameworks and libraries that let you make UI tests. I don't care which one you use. Just use one. You don't even have
to-- everybody's taking pictures of these,
nice-- you don't even have to use this one. You can literally do get
bound and client direct on your elements. And make sure they're
the right size, and the font size is the same. Do whatever you want, as
long as you test your shit. And finally remember, I told
you elements are composable. And they should except
children, and they should work in other things. So if your elements
should be composable, and that's a thing
that you care about, make sure that you test it. If you're writing something
that's like a form, put all sorts of
things in that form, and make sure that
it doesn't crash. If you thing is like an
input, put it inside a form and see that it works fine. Test your things. Cool. We're testing. We have semver. We're telling the users
we're updating our elements. Users trust us. They're delighted
with our elements. They're going to
use them forever. We need to actually write
documentation about it. Because if you don't WTFM,
you can't tell people to RTFM later. So cover your bases now. If your element has any
edge cases, document them. I don't care that
your element is being weird, if it's
in like RTL mode, as long as you tell me about it. Because otherwise I'm going to
write this super lonely stack overflow post that nobody's
going to respond to. And I'm just going
to be sitting there. And be like, it's been 10 hours. Why doesn't this element work? Just document your shit. It's going to be great. Whew. We're maintaining our element. Everything is great. Let's talk about performance. So performance has been a big
topic at I/O. Performing apps, we want fast apps, fast apps
lead to user engagement, lead to more views, leads
to me getting promoted and getting paid more. Everybody wants that. But when we talk about
elements, performance is actually really important. Because it doesn't matter how
fast I make my application. I can use Rail and
PRPL and everything. If I'm building it out of really
terrible and slow elements, there is nothing that I can do. Which means that you
as an element developer have to be very careful about
what you put in an element. Because it's going to screw
somebody in a major way later. So if you think
about your element, maybe it's like one
millisecond fast. Let's say it's a checkbox and it
takes one millisecond to paint. Because that's what we
really-- oh, do one thing. Do it fast. Duh. So if you think
about painting, if it takes one millisecond
to paint your element, you might high five
yourself, and be like, one millisecond is
the fastest paint I've ever heard of in my life. I'm doing great. But if I have 1,000 pizza
toppings on that page, and they're all
checkboxes, you've now added a whole
second to that page. And a whole second to a web
page is actually enormous. We've been trying to save
milliseconds out of pages. And you just made
it so much slower. So focus on first paint. And make sure that the
first time your element shows up on the page, is as
fast as that can possibly be. Steve Orwell, on
the Polymer team, has an amazing rule about this. The best to advice about how
to make your element be fast, is do less and be lazy. This applies to anything
that you want to be fast. Do less. Be lazy. By do less, we
literally mean that. Don't do anything
you don't need. Before first paint. Don't set magical handlers. Don't set magical styles
that are needed maybe later. So we had this code a lot in
a lot of our Polymer elements, where when the element
was being attached, so when it was actually
inserted in the DOM, we were updating the
pointer events, to make sure you couldn't click
on disabled things. And we were adding
click handlers. And this looks like a very
reasonable code, right? It's very short. It probably doesn't
take very long to run. But again, if you
do it 1,000 times, that's 1,000 event listeners
you're setting up before you're painting the page. That's enormous. So what we do now is we wrap
it in this afterNextRender. We do everything that's
needed for paint. This isn't needed
for first paint. And everything that's
needed, literally the tick right it painted, we
do it after the next render. And this is really great. Because now my page
paints really fast. My elements paint really fast. And they're interactable,
instantly right after. So everything is perfect
and everything is fast. Be lazy takes that
one step further. Don't do anything
unless somebody actually asks you for it. Don't just volunteer to do work. That's bonkers. You would never do
that in real life. I have nothing to do right now. Let me do some work. It's great. You watch Netflix. You know you do. So in Polymer we have a
lot of Polymer elements. They implement the
material design spec. And the material design spec
has this thing where every time you click on something, it has
a really satisfactory ripple that is a little jiggle. And everything is
really nice and fun. So the way we were
coding it up is that literally every element had
a ripple element inside of it. Checkboxes, buttons, inputs;
everything had a ripple. Which sounds really
great, in theory, right? It should ripple. We should put a ripple
element in there. It turns out that's crazy. Let's go back to my
pizza topping analogy. I have 1,000 pizza toppings. I'm probably going to
click on four of them. Because I've tried to put all
the pizza toppings on a pizza before. And it is terrible. Don't do it. Pineapple and mushrooms
don't go together. They go together
with onions though. So if you're only going
to click on three things, you only need three ripples. You're now creating 997 ripples
you don't actually need. So we updated our code. And we do something else
now where no element has a ripple when it starts up. But if you click on
it, the first thing it's going to do on
that clicking would be, do I have a ripple? No. Well, here's a ripple. Make it jiggle. So now in this
enormous application we're only creating the
ripples we actually need. We're being incredibly lazy. And this makes
everything super fast. Because I'm not just
creating dominoes that are sitting on the page
doing absolutely nothing, not even giving them
access to Netflix. Do less. Be lazy. Do less. Be lazy. This is your mantra. Tattoo it somewhere. And we didn't just come
up with us one day. Well, Steve did. He woke up. He's listening to this
weird podcast, I think, that tells him that. But we actually started
writing test for performance to figure out how
this was going. And there's many
different ways in which you can test performance. And they're all terrifying. Because I'm actually terrified
of everybody else's frameworks. So I have two simple ones that I
use, and they work really well. The first one is console.time. So console.time takes
a label, and basically between the first time
you call time and time end on that label, it calculates
how much time this cost. And you can also nest them. So you can be like, well
creation took this long, but setting attributes
took this long. And the reason why
console.time is nice is because you get a
timeline in the dev tools, and you can see what's
actually happening here. This is incredibly fast. Because I was just doing
random numbers in a loop. You're never going to
get a code that runs in 10 milliseconds like that. But yeah, so that's
console.time. It gives you a timeline. If you're even lazier than that,
and you don't care about that, you can use
performance.now, which literally just tells
you milliseconds now, milliseconds now. So you can do it before and
you can do it after a task, and see how long that took. And the thing that
you do inside, if you want to test
your first paint, is that you want to
create your element. You want to attach
it to the body. And you want to do a giant hack. So let's talk about
this giant hack. In the same way that we're
optimizing our elements, the browser has been
optimizing itself. Because it assumes
that we're terrible developers, which we are. So just because you're
appending something to the body, it doesn't actually mean
Chrome is going to paint it. Chrome going to
wait to batch them. If that thing isn't visible,
Chrome doesn't even care. If it doesn't affect the
layout it doesn't care. And you can't actually tell
Chrome to paint things. So the only way we can
time this correctly is by sort of forcing Chrome
to re-layout the entire page, which also forces it to paint. offsetWidth is one
of these attributes that when you call it on an
element as a style attribute. It has to recalculate
the layout. Because it's in
reference to its parents. So that's the one that I use. Pretty much anything with
the word offset in it, is going to cause a re-layout. You can Google for all the
other ones if you don't like it. But the idea here
is that if you want to make sure your
element has painted, somehow trigger a
re-layout on the page. And the follow-up to that
is don't do this once. Do it 1,000 times. Do it as many times
as you have time for. Because if you only
do it once, anything could have happened in there. Somebody could have sent you an
animated gif to your slot GNL, which slows down your computer. The garbage collector
could have run. The garbage collector
could have not run. If you do it 1,000 times, you'll
get more accurate numbers. You actually get a good
answer about how slow or how fast your
element is painting. And the reason why
this is awesome is that now you can automate it. You can put this in a unit test. You can put it on a test
that you run on every merge. And then every merge
you can be like, well this element was 10
milliseconds fast yesterday, and now it's 15. And then you can ask yourself
whether the feature you're adding or the bug
fix you're adding is actually worth this
performance cost you're taking. So let's talk about
accessibility. There's this amazing
quote about-- so anyhow, the conclusion here just
to like bring it home, is test your elements
for performance. Make sure they are fast. If your elements are
really slow, I hate you. And you're going to
slow down the web. Please don't slow down the web. It's really hard for all of us. Accessibility, so
there's this is amazing quote by Cordelia Dillon,
which is that accessibility is like a blueberry muffin. So the way you make a
blueberry muffin isn't by taking a plain muffin
and a fistful of blueberries and jamming them in
there, and be like, I made you a blueberry muffin. You made me garbage. The way you make
a blueberry muffin is by taking the
eggs and the flour and the sugar and the butter
and beating them together, and adding the blueberries
to this raw dough and putting them in the oven,
and waiting for 35 minutes. And then you get delicious
blueberry muffins. Accessibility is hard. You have to do it
the entire time from the birth of your element
to the end of your element, in the same way that
you make muffins. You can't just make an
element and the last day before you ship
it, be like, shit I didn't make it accessible. Let me jam some aria
labels in there. You're going to make a
terrible job about it. And the reason why
this is important is that if you don't
have accessible elements, you're not going to be able
to make accessible apps. And if you don't want
to make accessible apps, you're a terrible person. And you shouldn't be
making apps for anybody. You should be doing
something else. Thanks, you all. Rob Dodson gave a really
good talk yesterday at 9:00 AM on this
stage about how to make your elements accessible. And I strongly recommend
going and watching it at home. It's an amazing talk. And he tells you
proper, concrete things on how to make it better. I'm going to tell you two
things that I got wrong, because they were kind of
really easy things for me to get right, and I didn't. Focus states are
a really big one. Focus states tell you where
the focus is on the page. It's a really ugly
outline that in the 2000s, it was really cool to set
outline none on focus, because nobody really liked it. And that's really terrible. Because if you're
not using the mouse, and you're just
using a keyboard. You're not going to know
where you are on the page. But even if you are a mouse
user, if it's just you, remember the last time
you had to buy something on the internet? And at the end you get to the
15-field visa credit form, where you have to fill in all
your information, your shipping address, your mailing address,
your name and your credit card number. And you're going to be
tabbing through them. I promise you,
you don't actually click on every single field. I know you. And if nobody is
telling you where the focus is on
that page, you're going to start typing
your credit card number and your address field. You're going to get frustrated. It's already a frustrating
experience buying things on the internet. Don't make it worse. Don't make bad UIs for people. I don't care whether
you use this outline or a different outline, or
you're communicating focus in a different way, as long
as you are communicating focus in some way. You can make a nice
ripple around it. Just make sure that if
somebody is using the keyboard, they know where the
focus is on that page. And the platform
helps you with this. tabindex equals 0,
whatever you put it on that thing becomes focusable. And by default, at least it
gets the really ugly outline. It's ugly. But you're doing better than
not doing anything at all. And the other thing is that you
have document.activeElement, which tells you where the
focus is on that page. Which means now you can unit
test this and automate this. Make a test where you
have 17 of your elements, and simulate tabbing
through it, and check that the thing that is focused
is a thing that you expect to be focused, and
it's styled like you expect it to be focused. Unit tests are the best. They make sure that your
element doesn't randomly break. The platform also
gives you aria. Aria is what voiceover
applications use to read HTML. There's a whole bunch of
documentation on aria. I'm not going to
talk about aria. I just want to mention
that some elements have built-in aria like
NAV and A have extra aria built in themselves. And that ARIA-LABELLEDBY is
this really awesome attribute that is basically
ARIA-LABEL on steroids. Because if an element already
has a built-in aria label, like the native input does. It uses the aria label to
read whatever you typed in it. You can't put an extra
aria label on it. You can only have one. So if you want to make the
native input more accessible, like say with a label that
describes what it's for, ARIA-LABELLEDBY
is there for that. It always adds more
information to any element. So this is really important. Please make your
elements accessible. Because if we're going to
make accessible elements, we're going to get
accessible apps. And the same thing
happens for performance. If you have fast elements,
you're going to get a fast app. And if you have
maintainable elements, you're going to get
a maintainable app. And that's really our goal
as element developers. We want to make the web better. We want to make amazing
apps for other people. So, that's it. I hope you got something
out of this talk. Please go home
and make elements. And if you do, tweet them at
me, so I can see what you made. Thanks. [APPLAUSE] [MUSIC PLAYING]
This was a good video. Made me think about my component creation process in a different way