ROB: All right, how's it going?
Thank you guys so much for
coming out this morning.
I know it's a little early.
It's good to see you all
here bright and early.
What we're going to be talking
about today is Web Components.
You guys can come on up.
Sure, why not.
Grab a seat.
Grab a seat.
Now, for those of you who
didn't catch Dimitri's panel
the other day, I
just want to give you
kind of a quick,
high-level summary of what
Web Components are
and kind of what we're
going to be talking
about this morning.
So Web Components
give developers
the ability to extend
the HTML vocabulary.
And with that, we get
this much easier model
for creating reusable,
encapsulated little components
we can compose together.
Now, today there are
a handful of libraries
which are being built on top of
the Web Components standards.
You've got X-Tag, Bosonic, and
Polymer, by these guys up here.
And the cool thing
is that now that we
have this whole ecosystem of
tools that's available to us,
we have this growing
world of components
that are being built.
So you've got the Core
and the Paper element sets
have been produced
by the Polymer team.
You've got the Brick
set that's being
built by the folks at Mozilla.
And you also have a
whole slew of components
that are being built by
individuals out there,
put up on GitHub and shared on
sites like Component Kitchen
and CustomElements.io.
So with this big change
comes a lot of questions.
Developers are
wondering, what are
some of the best
practices around working
with Web Components?
And they also want to know,
when are these things going
to be production-ready?
When can we actually start
dropping these into our apps?
So to help answer some
of those questions today,
we've got a really great panel.
Just to introduce really
quickly down here at the end
we've got Matt McNulty,
who is the engineering team
manager for Polymer.
Next to him we
have Taylor Savage,
who is the product
manager for Polymer.
To my right, your
left, is going to be
Kevin Schaaf,
engineer on Polymer.
To my left, your right,
is Dimitri Glazkov,
godfather of Web Components
and software engineer on Blink.
DIMITRI: Uncle of
Web Components.
ROB: Uncle of Web Components.
Next to him we have Steve
Orvell, engineer on Polymer.
And at the end there
we have Alice Boxhall,
an engineer on the
Chrome team who
is specializing
in accessibility.
So we've got a lot
of good questions.
But if you out there in the
audience have a question,
we have a microphone up here.
And for those of you
watching on the live stream,
you can tweet
@ChromiumDev and we'll
try to get those questions
asked to the panel as well.
Let's start with
the first question
here, from Hector
Carmona, who wants
to know, "Are there
any steps that
must be taken to ensure
that an application is
accessible to screen readers
when working with Polymer?"
That sounds like a good
question for you, Alice.
ALICE: Yeah.
OK, so there's sort of a
couple of facets to that.
As mentioned-- I think
Matt mentioned yesterday--
when we talk about
Polymer, we're
talking about a few
different things.
So I'll address the
Polymer Paper elements
part of the question first.
So if you're using
Paper elements, by 1.0
you shouldn't have
to do anything extra.
So today the accessibility story
is a bit of a work in progress.
So you'll look at
some elements, you'll
see that they're
extremely accessible.
All the markup's been done.
Other elements, there's still
some work left to be done.
But by 1.0 they
should be-- Matt,
correct me if I'm wrong--
completely accessible.
[CHEERING AND APPLAUSE]
ALICE: So I know that the team
has been working incredibly
hard on that, and learning
a lot about accessibility.
So if you're not using
the Core or Paper
elements-- you are creating
your own elements-- yes,
there's definitely extra
work that you have to do.
And this is the work that the
Polymer team have been doing.
So essentially, what you have to
do is what you would do today.
Sort of what you would do in
the pre-Web Components world
to actually create
accessible custom widgets,
just built using divs
and spans and so on.
And that is to use
technologies like RER
to specify the semantics
of the elements.
So with native elements,
they're actually--
these semantics are
specified by the browser
and actually baked in.
When you're creating
custom elements,
you have to specify
your own semantics.
So there's plenty of resources
on the web on how to do this.
There's articles.
There's a Google DevBytes talk
that I gave for I/O this year,
which sort of outlines at a
high level what you need to do.
But yeah, the answer
is that you definitely
will need to do
extra work if you're
creating your own elements.
And that would be a
great thing to do.
ROB: Awesome.
Thanks.
All right, so our next question
comes from Cross Product--
I'm assuming that's
not your real name.
"If I'm adding third-party
components to my application,
how can I know that they'll
perform well and not
bloat the file size of my app?"
That seems like a good one
for either Kevin or Steve.
You guys have an opinion?
KEVIN: Yeah, yeah.
I can take a shot.
So the awesome thing
about encapsulation
is it hides complexity.
So the tricky thing
about encapsulation
is that it also
hides complexity.
Right?
So you pull in
this custom element
that you found in a catalog.
And the awesome thing
is you don't really
have to know what the guy-- what
kind of feats of engineering
the guy had to do
inside of it to make
this awesome spreadsheet
component or something.
But at the same time,
you're a little bit removed
from what's in there.
So I think there's two good
answers to this question.
One is, as Matt
mentioned yesterday,
we're doing a ton of work right
now on performance of Polymer.
We think composition is such an
awesome tool that you shouldn't
have to be limited
by having to think,
"Oh, do I need to only
put three things in here?
Because I need to worry
about performance."
So a lot of the
work we're doing it
so that you can much more
freely compose things
to get the right abstractions
and the right level
of componentization.
So performance, I think,
is a big answer to this.
Just so that you're not being
taxed for every custom element
that you're putting in there,
to the extent that you might be
today with the current
version in Polymer.
I think another answer
to this question
is really where the
community comes in.
So I think Rob
just mentioned, we
have kind of community-based
catalogs that are springing up.
So we have Component Kitchen
and CustomElements.io.
And we have Jan here in the
audience who's working on WebM.
ROB: [INAUDIBLE].
KEVIN: Oh, Enzio.
Great.
MATT: They're even sitting
next to each other.
KEVIN: And so, you know,
having these catalogs--
and especially once we have
things like reputation systems
in those catalogs, so that
you have four spreadsheet
components.
You know, the one that's
got 16 stars next to it
and has the payload
size mentioned,
and everyone raving about it.
These are the things that we can
have spring up in the community
to help people
navigate their way
through these third-party
elements in figuring out
which ones are the good ones.
ROB: Yeah, totally.
I think that we
definitely are going
to look towards the
community to stand up.
The sorts of catalogs
to help us figure out
what's the best stuff to use.
What should bubble to the top.
And really that's
just going to come
from folks using it,
trying it out, starring
things, and liking
them and whatnot.
And actually using
them in their projects.
All right, so the
next question is
going to come
from-- who is this?
Dave on the internet.
What's up, Dave?
Dave!
Dave, what up, dude?
"What solutions do you recommend
to manage dependencies and the
build process in a complex
application with Web
Components?"
In particular, I think Dave
is interested in things
like package managers.
And he's asking, are Bower
or NPM up to the job?
STEVE: OK, so.
First thing I want
to say is, at Polymer
we're building a library
fundamentally concerned
with making AIs using
custom elements to do so,
using these new Web
Component technologies.
The tools that you're
using for these things
are still on the table.
We're not taking
those away from you.
And the goal here is to sort
of build in a standard way
such that we plug into
your existing workflow
as well as we can.
Having said that, we've chosen
to use Bower as a mechanism
to get our components
to our users.
We think it's relatively good.
It serves our basic needs.
But we're certainly
not wedded to it,
and we're open to change here.
And we definitely recognize that
the NPM community is growing
and wants to provide
better front-end, sort
of client-side support
for pulling resources.
And we want to be nimble here,
and use the tools-- support
well the tools the
community wants.
So we certainly will
embrace the tools
as they mature to become useful.
And again, for us
right now, we found
that Bower filled the hole that
we needed, in the best way.
So having said that, as far
as managing dependencies--
HTML Imports is a
great way to do this.
So fundamentally, the unit of
what a thing is in HTML Imports
is HTML.
Which is makes a lot
of sense because this
is the fundamental thing that
we are actually building here,
is web pages that use HTML.
You can pull in actual
HTML declarative tags.
You can pull in CSS.
You can pull in scripts.
You can support composition.
You can nest imports
inside each other.
It's great.
And fundamentally,
we might ask, OK,
HTML Imports sounds good there,
but if I nest my resources
like that, that sounds like
a lot of network requests.
And we all know that
that's a potential issue.
So on the Polymer team, we
built a tool called Vulcanize.
And the tool basically
says, OK that's great,
you're using HTML Imports.
And when you go to
production with this,
you probably want to reduce
the number of network requests
you have.
And you can Vulcanize
your imports.
Basically what it
does is it just says,
OK, I'm going to concatenate.
Just like you would with script.
You concatenate those
imports into one file
so it can make one request.
And again, this fundamentally
solves that problem.
We also realize that there's
a lot of existing solutions.
And as I said, we
want to support those.
And there are a number
of module systems
that are really
focused around dealing
with JavaScript, primarily.
There's ES6 modules, which
is a standard that's coming.
There's AMD modules,
and there's RequireJS
There's a lot of
tools like that.
And I would like to say
that fundamentally, we
don't see really any core
issues with these things working
together with HTML Imports.
And I would like to say
that Quickoffice-- which
I know Matt spoke
about yesterday.
That's a big project
within Google
that uses Polymer
technologies-- actually
does use RequireJS and
HTML Imports together.
So again, we work
with it and make
sure there's no
rough edges there.
And we feel like fundamentally
this can work together well.
ROB: One thing I would
add to that, too,
is that I know that
in Vulcanize, we're
working to improve that tool
a bit so that it's easier
to exclude things from
different bundles.
You could actually break
your dependencies up
into your critical
elements, and maybe
your less critical elements.
And then lazy load
those at a later point.
Like right now, excluding stuff
in Vulcanize-- you can do it.
It's a little bit of work.
Because you have to
kind of know everything
that's in the other bundle.
And you've got to write
it all out line by line
and say, "Exclude all
these things individually."
We're working on
some changes that
might make that a lot easier.
Where you could just say,
"OK, in bundle B just exclude
everything from bundle A."
And that could make
it a lot easier
for you to then start
lazy loading things.
Another thing to consider.
Lazy loading is probably going
to be a bigger pattern that we
talk about in the
future, as we figure out
how we want that to
work in these apps.
All right.
Next question is, "Why
can't I keyboard tab through
the Polymer elements today"--
and I'm assuming they mean
the Core and the
Paper elements--
"And will this be fixed by 1.0?"
So that sounds like a
good question for Alice.
ALICE: All right.
Yeah, when I saw this question,
I kind of laughed to myself
and I was a little bit confused.
Because as I was
saying, the Polymer team
have been doing a lot of work
on accessibility and keyboard
handling is actually a
big part of accessibility.
As you can imagine.
If you're using a
screen reader, you're
really accessing things
a lot via the keyboard
if you're on a desktop device.
So I went and took a look.
And it turns out that most
stuff is keyboard accessible
and you can tab to it.
And there's just no focus dials.
So I think we need to punt this
one right along to the material
design panel later on,
and you can ask them
why there's no focus dials.
ROB: Sick burn!
KEVIN: So you're say
they are navigable.
There's just no visual
indication that focuses on it.
MATT: So there was briefly
a visual style on this--
that you can also ask
the material design
panel-- that involved pulsing.
And we actually, unfortunately,
left that in there
when we announced all the
material design stuff at I/O.
And then really
quickly removed it
because it was
incredibly irritating.
So now we just
haven't replaced it.
So we've got to work on that.
There's an entire
document on it.
DIMITRI: There's way too
much cross-panel pollination
going on here.
STEVE: One other
thing I wanted to add
was just give me an
opportunity to mention
some work that's ongoing here.
Shadow DOM kind of changed a
lot of fundamental behavior
about the browser
and custom elements,
and introduces a
lot of new stuff.
And so one of things that
we as a team like to do
is, if we see something that
the platform-- native elements
in the platform-- can
do that we can't do,
we ask guys like Dimitri.
And say, "Hey, can you
give us that power?
Can you fix that?"
And he says, "That's really hard
and nobody at other companies
is going to agree
and it's going to be
tough to do the
standards process."
But, you know, that's
why he's the godfather.
So one of the
areas, for example,
that came up specifically
with respect to focus
is, lots of times you want
to make a custom element.
And this might get
slightly complicated,
where, "Hey, I
want to be focused
but I want to maybe
delegate focus
to some control
that's inside of me."
And a perfect example of a
platform element that does this
is an input, which
is type="date".
In this case, you call
focus on the input
and inside that there's
individual editors
for the month, the
day, and the year.
And it works really well and it
integrates with the tab index
perfectly and it does
exactly what you think.
And if you try to do this
with a custom element today,
it's very tricky.
And you have to end up writing a
lot of code and it's difficult.
So actually, Alice
and I have been
working with a couple great
Blink engineers in Tokyo,
and there's ongoing
work to fix this.
And this is one of
these areas where
Blink is doing
implementation work.
We're going to make
sure it makes sense.
And the feedback will
go back into the spec.
And we'll make sure that
other browsers implement
this the same way.
But the bottom line is
you'll be able to create
custom elements that have this
kind of complex focus behavior
that the elements
in the platform do.
So it should be awesome.
ROB: Good.
Now, one of things that
you mentioned just then
was that sometimes
we want to add stuff.
And you go to Dimitri,
and you're like, "Hey,
can we add this?"
And he says, "Well, I don't
know if the other browser
makers are going
to agree on that."
And that's actually a larger
question that developers have.
So a lot of folks are
saying, "Web Components
seem really cool.
I want to use them.
But I've got to make sure
that if I'm using something
it's supported in all browsers."
Do you guys see there being
a problem with Web Components
picking up adoption in
some of the other browsers?
Are we ever going to reach
some sort of consensus on this?
I feel like that's a good
question for you, Dimitri.
DIMITRI: This is
a good question.
All right.
It's also a hard question.
Going first is hard in any case.
And gosh, I wish that we
didn't have to do this first
and somebody else would do Web
Components first and figure it
all out.
But it's us.
And yes, a lot of things that
we've done is not scientific.
It's intuition-based.
Because you can't get
data-driven about a feature
until you actually start
having usage of the feature.
And so there's a certain
chicken and egg problem.
You can't ship anything until
you get some usage out of it.
You can't get usage out
of it until you ship it.
And the thing that's
going to happen
is, yes, we will
probably realize
that there are some
mistakes we've made.
And we need to listen to
you and look at the patterns
that you're forming
around problems.
Identify those patterns
as either, "Oh, this
is a useless feature.
We can just remove it."
Or, "Oh, this problem
has not been solved yet,
so we need to solve it."
And similarly, as far as the
browser developer is concerned,
there is definitely going
to be interesting-- well,
we already are having really
good discussions with Mozilla--
for implementing Web Components.
And the way we wrote the spec,
for example, was very like,
"Well, this is how
it should work."
And turns out when you
have a different browser
implementation, "This
is how it should work"
is just a vague phrase
that doesn't make any sense
in the implementation context
of a different browser.
So we have to go
and tune the spec,
and kind of go,
"Oh, this actually
needs to be more
precise wording.
And this is a much more
difficult problem or question
to answer."
And so going through
this, as well,
is just going to be
an iterative process.
And I don't see this-- like I
mentioned earlier, yesterday
actually, with my presentation--
this is just the beginning.
Web Components are going
to grow and mature.
And as part of that,
there will be changes.
And we expect those changes.
And we talk to pretty
much every browser vendor.
All of them want
you to be happy.
And the gist of the uncertainty
is whether the Web Components
are solving the right problems.
And the best way to
find out is to have
you use it and react
to it and provide data.
And once we have data,
we can act on it.
And that's what
we're going to do.
MATT: One of the unique things
about the Polymer project
is being embedded
in the Chrome team.
We've done a lot of that
iteration throughout.
And basically none of
the specs exist today
in the form they were
in when we joined,
as a result of that iteration.
And even still there's
going to be things
that we've missed
as Polymer matures,
as Web Components matures.
These other vendors
come along that we'll
realize we have to change.
And we'll do that.
DIMITRI: And this was
a real informative--
may not be clearly
visible, but the process
of Polymer team
starting to first
chew on specs the way they
were was amazing to me.
Because, first of
all, they messed up
all of my perfect world.
Turns out that when you
design things by yourself,
you imagine things perfectly and
everything works exactly right.
But then when pesky
users come and start
trying to use your stuff,
everything falls apart.
And that was amazing, just
the process of watching it.
Adding functionality and
removing it and reshaping it
was a really good process.
And I fully expect
that this continues
to happen as more
users start using it.
I think we've got
the basics right,
but there's going to be
interesting things like focus
and figuring out, "How do you
do that multiple input thing?
What is the right
way to do this?"
And we're going to
see more of that.
STEVE: Add one thing
really quickly,
which is I think that when
I spoke to you previously
about focus, this is
primarily additive.
So this is not going to-- if
start relying on these things,
isn't going to change
fundamentally how you use it.
And then the one other
thing that I just recalled
and I want to mention
quickly is that we
have been collaborating
with Mozilla.
One very drilled-in
issue was, how
should define events
flow through Shadow DOM?
And this was a particular
topic in which Mozilla
add their-- I think
actually, their model
for thinking about
it was a little bit
different than the way that
it was implemented in Chrome.
And I don't think that the
Blink implementation for this
has changed yet,
but I think this
was an area of very
lively discussion.
And this is one of these
things that's super drilled-in.
And I think for the normal
developer you would not-- I
mean, you'd probably
write 1,000 applications
and never really
care about this.
But I think it's an
area where I actually
think that it's very
possible that the Blink
implementation will change based
on the input that Mozilla gave.
And this is one of these things
that you've got to hammer out.
So I think a lot of these
technologies or changes
are going to be additive.
And where they are
not additive, I
think we're really
looking at trying
to make them as
low-impact as possible.
And this is a case where I
think nobody would really
notice the change.
But it might make it easier
to get agreement and get
more people adopting it.
ROB: Cool.
And then kind of piggy-backing
off of that a little bit,
we have this question
from [INAUDIBLE].
He's saying, "Now that you
do have some browsers which
are picking up Web
Components, what
do we think about-- is
there going to come a time
where we don't need a
library like Polymer?
Where we don't want to use
a library like Polymer?
What does that look
like you guys?"
MATT: Well, I think
part of that question
probably comes from
a misunderstanding
that I talked about yesterday
around the polyfills being
part of Polymer.
We would love a world in which
we don't have polyfills at all.
Because it means
the Web Components
are out there and
widely accepted.
I don't think that's going
to happen for a while,
because I think
the web platform is
going to start
moving faster now.
And we're going to have
new technologies and things
like Service Worker
and Promises,
and all these things
coming that will require
polyfills going
on to the future.
So that polyfills as a tool
are never going to go away.
But the Web Components
ones certainly will.
Hopefully really soon.
So that was kind of part one.
And I lost my train of thought.
ROB: Sorry, so the
polyfills are going away,
but then what do you see
for Polymer in the future?
MATT: Yeah.
So above that Polymer
itself, there's
always going to be-- Polymer
is opinionated, right?
And it's going to
provide syntactic sugar.
So you want those
primitives to be primitive.
You want them to be so
expressive that no one up here
can think of all the
different uses for them.
Like with Dimitri
was talking to,
the intersection of your perfect
little world with actual users.
Those users are going
to come up with things
that are much more awesome
if you've got a really
low-level primitive
that's really expressive.
So to a certain
extent there's always
going to be room to
sugar those primitives.
And there's always
going to be room
to have an opinion and
a variety of opinions.
So there will be more
libraries like Polymer
that use Web Components
going forward.
And they'll have a place
for a really long time.
ROB: You mentioned
the polyfills there.
Another question that a
lot of developers have is,
what are we doing to
ensure that those polyfills
and Polymer in general
run well across all
these different browsers?
Because we are trying to
support a lot of things
on a lot of different platforms.
STEVE: I can speak
to that a little bit.
So fundamentally, when
we look at Web Components
we're talking about
custom elements,
HTML Imports, Shadow DOM,
things like the template tag.
And template is a good example.
There's actually pretty
good support for this now,
and it's really only IE
that doesn't have it.
And it's not the hardest
thing to polyfill.
Custom elements, as it turns,
it's incredibly convenient
for the browser
do all that work.
But you can write a polyfill
and it's not that bad
if your browser is modern.
If you go back to IE
10, it's very painful.
But we actually do support that.
If you go back further, we
said it's a little too hard.
But I think it's theoretically
possible to extend support
slightly further back
if there's demand.
HTML imports, again, it's
incredibly convenient
for the browser
do all that work.
And there are certain things
that are around fetching that
a polyfill really cannot do.
But fundamentally,
this is also something
that's not really
impossible to polyfill.
And so we definitely take
a lot of time and effort
to make sure that the Custom
Elements polyfill and the HTML
Imports polyfill
work really well
and are fundamentally
pretty sound.
And we don't feel like there's
huge caveats for using them.
Shadow DOM, on the other hand,
is a very, very, very difficult
thing to polyfill.
Fundamentally changes the
way the browser works.
MATT: We weren't entirely
sure you could polyfill that.
STEVE: Yeah.
And really this is one
of these things where
we had a couple engineers
that were almost too good.
They did almost too good
a job and sort of proved
that it was
fundamentally possible.
But what we have
found in practice
is there's a pretty
significant both performance
penalty to trying to polyfill
Shadow DOM correctly.
MATT: The point of polyfills
has never been performance.
STEVE: Yeah.
MATT: It's been compatibility.
If you can polyfill
something performantly,
you don't need
the native future.
STEVE: Yeah.
So this is one of
these things that's
actually really tough for us.
Because on the one
hand, we really
want to use this
awesome technology
to push this forward.
On the other hand,
it's really painful
to use it on a browser
that doesn't support it.
And not only is there
a performance problem
but there's a really
long tail of bugs
because it's fairly intrusive
to how-- again, fundamentally
changing the way
the browser works.
So we've done a good job
squashing those bugs.
And then there's another
thing, which is it
does CSS encapsulation,
which we love
and we hate depending
on your perspective.
But fundamentally,
this is something
that is exceptionally hard to
polyfill in a way that is not
like, "Oh, my page now
takes 10 minutes to load."
So what we chose to do for
CSS from the start was to say,
OK, we're not going to try
to be super-correct here.
We're going to try
to be practical.
And moving forward
with our new version,
we're stepping back and
taking a look at Shadow DOM
and trying to apply that same
rule a little more broadly.
And say we're going to be
a little bit less correct.
We're not to make as much--
we're going to still have
the polyfill, but we think
that practically speaking we
can get a lot of
the benefit here
having more of a shim
instead of a polyfill.
And what this would do is it
would allow us to-- again,
this is part of a vision in
our new version, 0.8-- to say,
oh you can use this in
browsers that don't support it.
And the penalty
for using Polymer
in browsers that don't
support these technologies
is not as great.
And yes, there are going to
be some trade-offs there.
Like you're not going to
get the same guarantees
that you do in Chrome.
However, with some cooperation,
we can get most of the benefit
and sort of prove out that
Web Components make sense
and get the feedback that
Dimitri was talking about.
If thousands of web pages
start using these things--
and mobile Safari mostly
works, but there's
a couple of issues with-- the
performance is good enough.
But there's some issues
with, "Oh, it's not native."
This is pressure for this to be,
we hope, adopted more widely.
ROB: Yeah.
And one other
thing that I wanted
to add there was we talked a
lot about how we're polyfilling
all these things in
different browsers,
but how are we actually
testing those polyfills?
What are we doing, and
how should developers
test these things?
Because as you
mentioned, behavior
is not exactly the same
under polyfill versus Chrome.
Are there things that people can
do to unit test their elements,
or integration test
their elements?
Like how would
developers do that today?
KEVIN: Yeah, so maybe
three or four months ago
we started to tackle
this problem head-on.
So the interesting thing about
Custom Elements-- and it's
a little unique from
other frameworks--
is that you're actually creating
an actual element in the DOM.
So you have this tight
coupling with the DOM.
So there's really no way
to test a Custom Element
outside the DOM, first of all.
So that was kind
of a unique problem
with just being able to build
a testing framework that
tests these things.
It requires the DOM.
So that's one.
And then, as you
say, because we have
this variable with the polyfills
across-- which introduce
slight differences in
behavior across platforms--
it was really
important that we were
able to easily on a
per check-in basis
be able to run our tests across
all these different browsers.
So we've been spending
a lot of time,
the last four months
or so, developing
what we're calling
Web Component Tester.
So it's kind of a framework.
And we're right now where we're
integrating with Sauce Labs
to be able to easily-- with
Sauce Labs and GitHub--
so that when you push
a change to a component
it can run continuous
integration across a suite
of browsers in the cloud and
return you those results.
So I think-- the intention is
that this same framework can
be rolled out and used on
anyone's third-party components
going forward.
So look for more
details on that.
I think we blogged maybe
a little bit about it.
MATT: Yeah, the 0.
5.1 release has got
some stuff about that.
ROB: Yeah,
blog.polymer-project.org has
a whole section on Web Component
Tester if you want to check
that out.
And I believe also we have
the Seed Element project,
which is up on GitHub at
PolymerLabs/ seed-element.
I believe.
Ian, if that is Using
Web Component Tester?
Yes.
OK.
So if you go and check out
the Seed Element as well,
that's basically an example.
You could just follow that.
Implement it with
your own element
to get some of those
tests up and running.
Switching gears a
little bit, let's talk
about some of the other
libraries that are out there.
Some of the other things which
were even shown yesterday here.
Yesterday, my British
doppelganger Matt Gaunt
got up here and showed
Google's Web Starter Kit.
And a lot of people are
interested to know, when is it
appropriate to use
Google Web Starter Kit?
When is it appropriate
to use Polymer?
And really, what are the
differences between the two?
Taylor?
TAYLOR: I can answer this.
Yeah.
So first starting off, kind
of reiterating the difference.
They're two totally
different tools.
So Polymer at its core is
for building components.
And you can build
little UI components
or you can build arbitrarily
complex components.
And with composition you can
nest these components together
to build entire apps.
And Web Starter Kit is
exactly what it sounds like.
It's a starter kit.
So it's a great
jumping off point.
It's a great skinning
of existing classic web
apps that are span and div.
And most importantly,
it's for older browsers.
So Polymer has
always been and will
continue to be future-facing.
We support evergreen browsers.
With the polyfills, we're able
to reach back a little bit more
and support slightly
older browsers.
With Web Starter Kit,
you get all the way back.
So if you want to get that
nice material design look, kind
of a light shim over your
existing classic web app,
Web Starter Kit's
a good way to go.
If you want to build these
complex, future-facing, really
nice, silky smooth web apps
with all kinds of behavior,
Polymer is probably
your way to go.
And then on top of this,
also, the Paper elements
is just one set of
componentss-- happen
to be built by the Polymer team
using Polymer-- that shows what
you can do by skinning
a whole set of elements
and making them work
specifically together.
And so that's our material
design implementation.
But again, it
composites and groups
the design into
different phases.
So we have things as
simple as buttons,
or we have entire
scaffolding layouts.
So if you want to
read, actually,
Web Starter Kit, you
can look through and get
a nice, top-to-bottom,
app-wide, "What
should the best
practices for design be?"
And with Polymer, we actually
implement these as components,
so you can drag and drop them,
and drop them in your app
as you'd like.
So that's kind of the
difference between Web Starter
Kit and Polymer.
ROB: Just to add to
that really quickly.
When I threw together the
website for the Polytechnics--
which is
itshackademic.com-- I really
just wanted a
traditional content site.
I wasn't trying to
build an application.
I was just trying to make a site
so people could go and figure
out where the Polytechnics were.
And for that, I didn't
actually use Web Starter Kit.
I was just using
regular HTML and SaaS.
Just kind of rolled
my own thing.
But I would have
used Web Starter Kit.
It would have been totally
reasonable to use it
in that situation.
There was one thing, though.
I had this really complex map
thing that I wanted to build.
And so for that, I used Polymer.
I built a widget out of Polymer.
I used it specifically
in that application.
So the two are not
mutually exclusive, either.
You could use Web Starter
Kit and Polymer together,
if you want.
You want maybe some
interesting widgets
that you want to
drop into that app.
So you could use both.
Now piggybacking
off of that, you've
also got libraries out there
like AngularJS and Ember.
One person is wondering, "With
AngularJS 2.x embracing Web
Components as well, can you guys
talk about how the two align
and which one should I choose?"
And this question was
asked by Carlos Santana.
So that's exciting!
I guess he's into guitar playing
as well as Web Components.
MATT: Yeah, he's a big
Angular enthusiast.
ROB: He's a real
Renaissance man, it seems.
So who would like
to take that one?
Matt?
MATT: Sure, I'll take it.
Yeah, so Angular is a
really popular library.
It's great.
People use it a lot.
We talk with them quite a bit.
It's awesome that they're
going to be supporting
Web Components with Angular 2.
We're going to have
to wait and see
a little bit to see
exactly what form
that support's going to take.
We'll have to wait
and see a little bit.
But it'll be great.
Regardless of that,
one of the great things
about Web Components
is that it's just HTML.
So unless your library
takes an optimization path
or ignores the fact that Custom
Elements could, ever exist,
you should be able to just drop
these things into any existing
app in any existing framework.
So I think as Web Components
becomes more popular,
it's going to be a lot easier
to do this kind of interop.
And then changes we're
making in Polymer 0.8,
using events for change
notification and things
like that, should also
help a lot of the interop.
So I think it's going to end
up-- Angular is really popular.
I think we're going to end
up with the pattern of using
Polymer elements in Angular.
And Angular and Polymer
together is probably
going to be a pretty
popular solution as well.
STEVE: The only thing
I want to add to this
is the future that we see is a
future in which you don't have
to choose A or B. You
can choose A and B.
And again, Custom Elements
provide a mechanism
that we can sort of make these
things lightweight enough
that they can be
used together easily.
ROB: All right, so
the next question.
Folks are wondering, is it the
plan of hybrid Polymer web apps
to be an alternative to
Android apps written in Java?
If so, when will they be equally
usable in terms of performance?
This is something
that actually I've
had a few people ask
me here at the event.
They come up and
they're like, well, I
see all these really
cool components
and I'm not quite sure.
Should I be building
a hybrid app?
Should I be building
a native app?
And how do I decide
between the two?
Matt?
MATT: I'll take that one again.
One of the awesome
things about the web
is its ubiquity and reach.
Right?
So it's across
basically every platform
that exists as a way
of doing web content.
Many, many, many native apps
use web content as well,
or hybrid apps today.
So it's great.
It's already there.
And we think Polymer
going to be a great way
to build apps across absolutely
any one of these platforms,
including things that
aren't internet connected.
HTML is an awesome
way to build UIs
regardless of whether it's
connected to the internet.
Yeah, so that said, performance.
Performance characteristics
are different
on every single
platform, both on the web
across different platforms
and native versus web.
I think there are, if you look
at our Topeka app from I/O,
it's got native quality
performance on Android.
Particular things in
Android's framework
are slow or janky, right?
Just like they are on the web.
It's just a different
flavor of janky.
So I think, that said, Chrome's
performance is improving
dramatically, especially
in the last year or so,
as we're finding it a lot
easier to build really
high-performance web
apps on Android lately.
And then iOS has always had
really smooth animations
and things like that.
So it's going to be
an evolving story.
And the great thing
is if you use the web,
you can kind of reach it all
ROB: And then piggybacking
off of that really quickly,
someone was asking,
would we recommend
going ahead and using Polymer
in a client application today?
And if not, why not?
And when is there a good time
for them to start doing that?
How are they going to know
when that good time is?
MATT: Are the Salesforce
guys still here?
I think we sort of
answer that yesterday.
I think that it is-- depending
on your level of tolerance
for being an early
adopter, you can absolutely
use these things today.
Salesforce and News
Corp and things
like that are examples of
that, as well as YouTube
and other Google
properties that are dipping
their toes in the
water as we speak.
So I think it's ready today.
And please use it, and
tell us if it's not.
And tell us exactly how.
And we'll fix it.
STEVE: The only
thing I would add
to that is just
that any of us who
have built complicated
applications on any platform--
you all know that it's
really easy to make
a thing that is very bad.
Right?
And I mean, the
way I like to think
about this is when you're using
the basic core building blocks
that the platform
you're using gives you,
what kind of head
room do you have?
When do you have to make
these tough decisions
about performance?
And when do you have
to optimize and say,
OK, this is a complicated thing.
I better figure out
how to do this in a way
that my application
doesn't really slow down.
And when is the platform
really supporting your use case
in a way that's helping you
from having to worry about this?
And this is one of the
areas that we really
felt like Polymer needed to
do a bit better, as Matt said.
So we want to try to
increase that head room such
that you can really feel
confident about using
these elements.
They feel lightweight.
And it doesn't feel
like, oh, I don't
want to include that
thing because it's
going to slow my app down.
So one of our
goals going forward
is you can do really well today.
They had room is there.
But our goal is to
increase that so that it
feels even better in the future.
ROB: And can you guys
talk a little bit
about what the differences are
in Polymer 0.8, specifically?
Like why is it so much smaller
than the previous version?
And did that simply come from
breaking the polyfills out,
or is the payload
smaller across the board?
What's the deal?
And why is it so different
in terms of performance?
MATT: Sure.
I can start that.
I'm sure Steve's going to jump
in right after me, though.
Right now I can say
the payload difference?
The biggest piece of
that was moving away
from our existing data binding
system and making that opt-in.
While creating a system
that's simpler but still
handles a lot of
the same use cases.
So wasn't breaking any
of the polyfills out.
We're still using the
Custom Elements polyfill.
We're still using the
HTML Imports polyfill.
And we will still have
a Shadow DOM shim.
That Shadow DOM shim will
probably be somewhat smaller,
but it's not a
driver of payload.
And similarly, we have-- we
didn't just cut features out
to reduce payload, as well.
Most of the features
are all still
there in a really similar form.
STEVE: Yeah, I would just
say maybe three points.
Fundamentally, Polymer
started a little bit
as a science project.
It was basically, can we
use these technologies
that this guy made and
make something cool?
And we're, as Matt
said yesterday,
I think we're pretty
successful in a lot of ways.
But one of the things that we
did when we did that was we
said, let's use these
technologies fundamentally
first and see if we
can make a good thing.
And we know the shape of the
thing that we want to make now.
And it totally makes sense.
And those principles
are not changing.
But one of things that we
did with this new version
is we sort of said,
OK, let's start
from the perspective of "We
need to make the thing that's
absolutely as fast as it can
be and add little bit by bit
layer, by layer, and not
slow down as we do so."
This was sort of a
fundamentally different process
and allows us to ensure
that everything's
tight and small and lean.
That's the first point.
The second point
is, as Matt said,
our data binding
system was really
good at dealing with
generalized generic data.
And that's excellent if
you have this problem,
and complicated apps often do.
But if you're making
a button, you probably
don't have this problem.
So to pay for that
system when you just
want to use a button, not
necessarily a great trade-off.
So this is where we said, "We
need a lighter-weight thing
for a lot of elements
that we're making."
And that led to a big complexity
reduction and size reduction
and speed improvement.
And then the last point
is just on Shadow DOM.
The Shadow DOM polyfill is big
and tries to be very correct.
And again, our goal
here is to say,
"We need to be leaner
and meaner here."
Both in terms of code
size and also in terms
of actual basic functionality.
We're going cut it
to the core and get
just what we need to prove
out this technology is
going to be
fundamentally viable.
So that all put together
seems pretty good so far.
MATT: Lots of lames.
ROB: Yeah.
And sort of following on that.
Charles [INAUDIBLE] from
Twitter is wondering, "How can
we actually start using 0.8?
Even though it is
new and experimental,
how can we actually start
playing around with it,
and will there be a list of
possible breaking changes?"
STEVE: Yeah.
Totally.
So right now-- did we announce?
I don't know.
Right now in the
Polymer GitHub repo
there's actually a branch
called 0.8 preview.
I don't really recommend
anyone poke too hard
at that because it's very early.
But you can get some-- if
you're really interested,
you can get some basic ideas
of the directions we're going.
Stay tuned.
"Coming soon" is what
I can say about that.
What was the other
part about it?
KEVIN: Yeah, as
far as the breaking
changes-- so as
Matt said, we hope
to make it around a
few minor versions
worth of breaking changes.
I don't think we've
got it buttoned
up enough to be able
to write those yet.
But we'll certainly have
something like a migration
guide when we get
to the point where
we're going to release
it, to guide people
on how to migrate
their code over.
And the last thing I'll say
is that I think, conceptually,
the way that you're thinking
about composing and building
applications using Polymer?
All of those concepts, 100%,
nothing there is changing.
It's really going
to be very small.
Just minor syntactical-type
changes I think,
that'll be involved in
going from 0.5 to 0.8.
ROB: Yeah, that's really
one of the benefits
of working with components
is that as someone consuming
the component, you
only really care
about the external
interface of that component.
You don't really need to or want
to know about the internals.
And so if those are getting
tweaked, it's totally OK.
It shouldn't really affect you.
And that's sort of
the beauty of it.
Which is something
that you really
don't have today on the web.
If you're using
Twitter Bootstrap,
and they need to change
a div in their nav bar,
well, you better copy
and paste a whole bunch
of new markup in
your application,
because you're going
to need that new div.
Whereas with a component that
can be inside the Shadow DOM,
for instance, and you can
just say, power update.
Get the new thing.
And move along.
Which is really nice.
I just want to remind
folks, because some people
are asking if they can
ask live questions.
We do have a
microphone right here.
I apologize for not
pointing that out earlier.
If you do-- anyone here
in the audience who
wants to come up
and ask something,
if you just come stand at the
mic, I will call upon you.
Let's actually move
into a little bit
more technical specifics.
Because people have
questions about how
to do particular
things with just
Web Components and
Polymer as well.
One question that we
have here is, "When is it
appropriate to put things in
the Shadow DOM versus the Light
DOM?"
And I'm curious, Dimitri, if
you have an opinion on that.
DIMITRI: It's a good question.
I think a lot of these
assumptions and opinions
are going to vary.
And how people start
using, building frameworks
around this, and building
toolkits around this.
My thinking always
had been that if you
want to make things composeable,
the composition boundaries
that you imagine is where
Shadow DOM and Light DOM meet.
So I would start-- I would not
say when is it appropriate?
That's not the right question.
So I guess that
was a bad question.
Sorry.
And I said it was
a good question.
The right question is, when
do you need to separate?
And answering that
question is very
specific for your application.
So if you need to
compose things together
and they need to stay
separate, then one of them
goes in the Shadow DOM, one
of them goes in the Light DOM.
If you don't want to do that
and don't need any of this ever,
then you don't need Shadow DOM.
KEVIN: I think one way that
you can conceptualize this
in your head is to think about
private API and public API.
So the things that you put in
the Shadow DOM of your Custom
Element are really the private
internals of your component.
The things that need to make
it go, that the user of it
really doesn't have to think
about or know about or care
about or have access to.
And the insertion
points that you
put-- so the content element
that you put in your Shadow DOM
is really exposing where
the public APIs of that
are for composition.
So that's the place where
users can pass Light DOM in,
and then you can decide, the
author of that public API,
how that expresses itself into
the DOM of your Custom Element.
So that's, I think, a way that
users can think about that.
STEVE: The only other
thing I would add
is just that, I know
this question sometimes
will be people asking
about things like search.
Like, well, if I
have one element
and how's my page
going to be crawl-able?
And this is an
important question.
I know that making
stuff for the web,
this is something that comes up.
It's critically important.
And the company we're at here
as something to do with that.
And that's a good question.
I think what I will say in
response is, that what we think
is great about Custom
Elements and Shadow DOM is
their support for composition.
When you're making
the system that
is really good at
that thing, it really
is unfortunate to have to
worry about essentially what
is a detail.
How the external
structure is to this tool.
So, I mean, one of the
things we're trying to do
is push the technology
forward to try
to make the tools
smarter at dealing
with these types of things.
It's almost as if you-- here's
my attempt at an analogy-- you
used LEGOs and they were
great at building things,
but you only allowed someone
to look at your LEGO thing
from the top down.
And it was kind
of lame that way.
Right?
So you just look at it
from a different angle,
and oh, it's three dimensional.
It's awesome.
So "tools evolve" is where I go.
ROB: We have a question
right here in the audience.
AUDIENCE: Yeah,
so this question's
related to that question.
When you have injection
points going into a shadow
DOM-- so let's say
you have an accordion,
and the actual content that
are going into the panels
are injected content.
And so they're part
of the public API,
but as soon as they
go into the Shadow DOM
they're kind of
private API that point.
How would you deal
with like, let's say,
a user has a Tooltip plugin
that they're trying to use,
and I want to show Tooltips on
the content of the accordion,
but the accordion is
now in the Shadow DOM?
KEVIN: To be clear, if
you have an accordion,
it has an insertion
point, so the accordion
is creating some divs
around open and close,
that sort of thing.
That's all kind of
hidden from the user.
But the content that the user
passes in through the Light DOM
really stays in the
scope of the user.
And so they should be fully able
to compose a Tooltip decorator,
or whatever, around the Light
DOM that they're passing in.
So I think these use cases
should be well supported.
STEVE: The only
thing I would add
is, today, before Shadow
DOM, the DOM of the browser
is kind of Wild West.
If I want to make a thing that,
say, makes all buttons blue,
I can do that with CSS.
If I wanted to make a
thing that makes a Tooltip
plugin for anything
in the whole universe,
I can do that with
jQuery really easily.
And what we introduced with
Custom Elements and Shadow DOM
is this fundamental
concept of scoping.
And the idea is that this
helps you with composition.
And that's really
what it's there for,
is to help you with composition.
So there are times when
you go, if somebody,
say-- so as Kevin said, if
I'm a Custom Element guy
and I go, "I want to use the
Tooltip plugin in my Custom
Element," that
should work great.
The support for that is there.
If I'm a guy that goes,
"Regardless of what content
is on my page that
uses Custom Elements
and may use Shadow DOM, I want
to use that Tooltip plugin
and have it apply globally,"
there we have a tension.
We have a tension between
composition and encapsulation.
I mean, one guy is
going to say, "I
don't want my button
inside my scope
to be-- I want it to be
protected from that guy who
tries to use this crazy Tooltip
plugin that I don't want."
Another guy's going
to go, "I want
that button inside that scope.
I don't know about it, but
I want that Tooltip plugin
to be applied."
And this is something
where there's really
no fundamentally right answer,
and we have to evolve the way
that we build things,
such that it makes sense.
I mean, fundamentally,
this is something
that we're hoping to address
better moving forward.
And I just think, stay tuned
for additional opinions
and support for this in Polymer.
ROB: Yes, Scott, do
you have another one?
AUDIENCE: So as a
library developer,
if somebody is
using your library
and they're trying to
interact with content that's
injected into the Shadow
DOM, should the answer today
be "We will not help you"?
Because this needs to be figured
out in the Shadow DOM and Web
Components?
STEVE: I wouldn't go that far.
What I would say is, again, I
see two fundamental use cases.
Use case number
one, guy is like,
"I don't want to
be-- I don't want
you to deal with my internals."
Use case number two, guy
from the outside says,
"I want to tweak this thing."
Fundamentally, I think the
best pattern, moving forward,
is a situation where
if a Guy A made
Custom Element and Guy
B is trying to use it
and has this need, that there's
an evolution of the Custom
Element so that it
supports that use case.
That's a process, right?
And in the interim,
Guy B might go,
"I'm going to fork your
code and change it."
Or fundamentally, one of the
things that Shadow DOM started
as a couple years
ago, it started
with a much stronger
encapsulated boundary.
And practically speaking,
as users, what we did was we
softened it a bit.
So for example, initially there
was no shadow root property.
So there was no way to get
at those elements inside.
Today there is.
So it is certainly possible
for you as a user to say,
"I need to poke at the
innards of that thing."
It's not the greatest pattern,
because it's somewhat brittle.
But it's possible.
And again, the best solution
is for sort of communication
and the Custom
Element that you're
using to provide the
API that it needs.
ROB: Steve, really
quick, can you
explain, why was that
boundary softened?
Like, was there a
reason for doing that?
KEVIN: It's precisely
because of this tension.
I mean, it's interesting, right?
So through Shadow DOM
and these technologies
we're bringing--
like Steve said--
we're bringing this
concept of scoping
to the web, which
really hasn't there.
It's been this
huge global thing.
Like all the CSS
and all of the DOM.
It's all in this one
big global thing.
Which is kind of crazy.
When you look at any other
computing environment,
you would say that's crazy.
So we're bringing this
concept of scoping.
And then all of the
sudden you start
to feel a little bit of
this pain of taking away
this kind of global toy-- like,
often misused but sometimes
useful, global query
selectors and global style.
And so those things are
definitely in tension.
And I think it's up
to us to help evolve
more tools for helping
you do these kind
of cross-cutting types
of things, like theming
and they use case
sales [INAUDIBLE].
ROB: Yeah, and
actually, I'm going
to get you guys really quickly.
But you mentioned theming and
that is a common question.
So someone asked, "What
are the best practices
for managing and coordinating
styles between different Custom
Elements so the design
appears coherent?"
This is from William
in Silicon Valley.
There's a little addendum
to this, which is,
"Is anybody else concerned that
the /deep combinator is going
to end up feeling like important
if you're on a really big
project?"
Like too many people using deep
and that's the new important.
So what do you guys say
about theming and deep?
STEVE: Yeah, I
can speak to that.
This is a big topic.
And I just want to
say a few things.
I think we're pretty unhappy
with deep and [INAUDIBLE]
shadow, which is its cousin.
Because they feel too blunt.
And also because
Blink guys tell us
they're really
hard to make fast.
So Polymer is going
to try to not rely
on those, moving forward.
And it makes it
tough, because we
have to adopt other strategies.
And one of those strategies,
we have an element
called Core Style
that we want to evolve
and make more powerful.
But the notion
basically is there's
an interaction between the
styles that an element needs
and where it's
getting them from.
ROB: All right.
Question from the audience.
AUDIENCE: Hi.
I'm David from the
Pinterest web team.
And we love Web Components
and we want to use Polymer.
Unfortunately, we
have to support
Android browser, IE8, IE9.
Is there any sort of
graceful degradation guides
that you have, maybe
internally, or that you
would consider writing?
ROB: I have an opinion on that.
Can I take it?
Can I take it?
OK!
So one thing to consider, if
you have to support those older
legacy browsers, is there's
a few different options
so you can go about it.
First of all, you don't have
to use all the Web Components
standards.
You could just, for instance,
just use Custom Elements.
And the polyfill for
Custom Elements, I believe
should work on Android
browser and IE9, maybe?
The polyfill for
Custom Elements?
I know that someone has done a
variation of that polyfill that
does work on IE9 and
an entry browser.
There's a variation-- I
think it's just call Document
Register Element or
something, by [INAUDIBLE].
MATT: Oddly enough, the Shadow
DOM polyfill works in IE9.
ROB: Interesting.
But I guess what I'm getting at
here is that Custom Elements--
I don't know if
it's our polyfill,
but there is a polyfill
out there, at least,
that does support
Custom Elements.
You could consider just using
that, just as a starting point.
I believe what GitHub does,
too, is they do-- maybe
I shouldn't say this-- but
they do user agent sniffing.
And they figure
out, is this person
going to be able to
support Web Components?
If so, then maybe I'll give
them the Web Component flavor.
And if not, maybe not.
But the other thing that they
do, which is really good,
is they're using
a type extension
elements for their
little time element
that is on the GitHub
website right now.
They've created a
Custom Element that
extends the native time element.
And so they take a time element.
They put a time-stamp
in it on the server,
and they send that down.
Now if the browser does not
work with Web Components,
you still get a time-stamp.
If it does work
with Web Components,
well then, that thing kicks
in and starts figuring out
the relative time
difference and everything.
So you get the progressive
enhancement there.
So maybe look at
Custom Elements.
Maybe look at type
extension elements,
because that way they
give you good fallbacks.
Those are my two big
opinions on that.
Anyone else?
MATT: Send the older
browsers to an older version.
ROB: Yeah.
AUDIENCE: Thanks.
ROB: So I think we only have
time for one last question.
We'll take one
from the audience.
Yes.
AUDIENCE: JB, SunGard
consulting services.
So you said that you're
removing some things
from some of the polyfills.
What sort of things
you're going to do?
What things are performant?
And if things are
really un-performant,
what kind of things are
really un-performant?
And what are we going to have to
do for IE10 and older browsers?
STEVE: Sure.
I mean, I think
fundamentally, around this, I
think I would speak
to Shadow DOM.
ROB: And Steve, if I may?
Keep it short.
STEVE: OK.
So Shadow DOM polyfill
as it is today
tries to provide a
completely correct view
of the entire universe.
Our goal with the new shim is
to say, "We don't necessarily
need that.
Instead, what we need is
a completely correct view
from the perspective of the
element that uses Shadow DOM."
By doing that, we can get a
pretty massive performance
improvement.
KEVIN: Massive
simplification that
still covers 95%
of the use cases
that users are going to need.
STEVE: Yeah, and the
other thing I would say
is that the polyfill
still exists
for the guy who wants
the more correct view.
ROB: Cool.
All right, well, I
want to thank everyone
on the panel for
coming out today.
Hopefully for you
guys this has been
an illuminating discussion.
Thank you for everyone who
submitted questions to us.
If you still have more
questions, for those of you
here in the
audience, we're going
to be having breakout
sessions later in the day,
I believe upstairs.
So come grab some of us.
We'll also be sort
of floating around
throughout the afternoon.
Also, for those of you who had
questions on the moderator that
were not answered, we're
going to try and answer those
after the fact.
So if you didn't get
your answer today
but it was on the
moderator, we're
going to follow up
and try and give you
a response for all
of those things.
So thank you all so much for
being with us this afternoon.
Or this morning.
