JAKE ARCHIBALD: I'm
supposed to be-- we're supposed to be
doing this now, aren't we? All right. Well let's-- SURMA: That's our intro. JAKE ARCHIBALD: OK. Excellent. [THEME MUSIC] YouTube comments. SURMA: They're sadly a thing. JAKE ARCHIBALD: They
are sadly a thing, but we have been
listening to them. SURMA: Some of them, yes. The ones that
actually have a point. JAKE ARCHIBALD: Well-- SURMA: Not all of them do. JAKE ARCHIBALD: There's
some good points that are being made-- recently increasing. So people have been noticing
my impending baldness. That's something that has been
coming up in the comments. Thank you for everyone
who has been-- SURMA: And noticing
me that I don't ever let you finish a sentence. JAKE ARCHIBALD: Has
that been noticed? SURMA: Yes. JAKE ARCHIBALD: Oh, well, we
could talk about that in a bit. But one of the things I-- we have noticed
and listened to is people saying, when
we talk about code, can we show some code? SURMA: Yeah, that
might be helpful. JAKE ARCHIBALD: So-- SURMA: Could be nice. JAKE ARCHIBALD:
We thought like-- we've got a camera-- we got an iPad here
with some code on it. So tree shaking. SURMA: Oh! So let me guess. You're just doing
this so we can put a nice buzzword in the title. JAKE ARCHIBALD: Yes. SURMA: 12 things you didn't
know about tree shaking. Number four will blow your mind! JAKE ARCHIBALD:
Class-based Tree Shaking is the title of this I think. So here we go. We've got a code example here. I'm importing a load of stuff. SURMA: Plugging your
own library are we? JAKE ARCHIBALD: It's
based on a true story, like all good stories are. I'm importing a load of stuff. This file has a
lot of stuff in it, but I'm only using two of them. And like modern
tools like roll up-- SURMA: Then why are you
importing the other ones? JAKE ARCHIBALD: Well, just
to show that they're there. Yes, technically I wouldn't
have to import them. SURMA: I mean,
commonly, I guess, you would import this as
import IDB key valid from-- put it all of them in
an object so you have-- JAKE ARCHIBALD: No. No. SURMA: No, you wouldn't. JAKE ARCHIBALD: No,
you wouldn't do that. SURMA: I wouldn't do that. JAKE ARCHIBALD: Good. So in this-- each
of these methods is individually exported, and
that means that tools like roll up and Web Packer can go,
you're only using two of these or three of these. And it goes, well,
I'm just going to take the ones you're
not using and delete them. SURMA: And that's tree shaking? JAKE ARCHIBALD: And
that's tree shaking. And that's good. SURMA: Oh, because the
tool can figure out what you're using, because
if you don't import them, you can't use them. JAKE ARCHIBALD: Right. SURMA: That's how
modules work, right? JAKE ARCHIBALD: Right. So in the days where
we would import jQuery, and you've got 101
methods, and you're only using three of them-- tough. You were taking the full
weight of each query. And with tree shaking,
that's not true, because you're only using
the stuff you actually import and use. So, yeah, this is great. This works fine, but I
ran into this problem. So say this is a
library, real library, and someone said, well, it's
all fine having set and get and all of these
things, but I want to create my own store
with-- that doesn't clash with another store. I was like, well, I
know how this works. So I made it happen. And so I thought, well,
it could be like this. SURMA: Now you're
importing a store? Oh, yeah, that's the common-- you now wouldn't just
[INAUDIBLE] the thing, but you have to instantiate
the whole thing first. JAKE ARCHIBALD: And it knows
all of its stuff about where the database connection is and
all of that, and it can go. But the problem is classes
can't be tree shooken-- SURMA: [LAUGHS] JAKE ARCHIBALD: I'm sure that's
the right way of saying that. SURMA: Oh, so, OK. So you have a class. It's called store. In the constructor,
as we can see here, it gets the backing
store name, the IDB-- did it call a store an IDB? JAKE ARCHIBALD: Yeah. Object store. SURMA: And then the class
of it has all these methods, like get and set, but
also the other ones we saw previously, like
keys and whatever that was. JAKE ARCHIBALD: Yeah. SURMA: OK. So but if you don't
use one of them-- ideally you wouldn't--
load the code. Right? JAKE ARCHIBALD: But
it's not statically analyzable in the same
way a function is. So here I'm using
dark keys, but I'm not using the delete method. I'm not using the clear method. But it has no way of
being sure about that. Because keys like this,
it looks like that static in the analyzable. But there are many other ways-- SURMA: That's what I meant. You can do very weird things. JAKE ARCHIBALD: Right. Exactly. So you can do as a
string, but that string could be like two
strings added together, or it could be some
sort of functional-- SURMA: If I ever see anyone
writing code in the last line, I will hunt that person down. JAKE ARCHIBALD: But there are
legitimate reasons to do that. You might have a
series of method names, and you want to append on to the
start or remove from the start. SURMA: Yeah, I've
done that myself. If you build your own little
meta-programming thing where you generate event
headers on the fly, this can happen in
real production code. This is not you being stupid. This is-- this can happen. JAKE ARCHIBALD: It can happen. And so my question really is,
how do we solve this problem? And spoiler alert, I don't
really have the answer, but I've seen other
libraries have done. So one example is this
is the style of RXJS. So here we're
importing the store. So we got our store. It doesn't have the
keys method on it, because that's, let's say, a
less common method to call. SURMA: Sure. JAKE ARCHIBALD: But you import
another JavaScript file, which has the keys
implementation in it. SURMA: And that just
mutates the prototype? JAKE ARCHIBALD: It
mutates to prototype. Exactly. So this would be
the implementation. SURMA: I mean, it works. I totally get it. JAKE ARCHIBALD: Yeah. SURMA: I'm always wary when
suddenly the order of imports matter. I feel like that's a
dangerous path to go down. And generally, like,
mutating the prototype is-- it's been done for years. I'm not saying
it's bad or stupid. It's just-- it feels dirty. It feels like that should
be a better solution. JAKE ARCHIBALD: Absolutely. And part the problem
with this as well is if you import it but
don't use it, tough. Because it's not statically
analyzable once again. You know, roll up
or a [INAUDIBLE].. SURMA: So it shifts the
burden onto the developer rather than just
being a tooling issue? JAKE ARCHIBALD:
Yeah, and it means you end up doing this
import for every method. It's kind of long strings. It's a bit messy. So thinking about other
ways of doing this, and there's a JavaScript
proposal which I really like, I'm a big fan of, called
the bind operator. SURMA: Yes. I remember the bind operator. JAKE ARCHIBALD: So
here we're importing store and the methods-- SURMA: So store, basically,
just in this specific, then it would practically more
or less be an empty class. That's not much in there. JAKE ARCHIBALD: Exactly. And you would call it like this. Store call it, call on set. And that's essentially saying
call the set method as if it were an instance of store. SURMA: If you have a
function in JavaScript, you can use dot call. You cannot just use
parentheses to invoke it, but you can use dot call. And then you give
it what should be this inside the
function like this, what is this supposed
to be, and here I have an N, what
the parameters are. And the bind operator just
says, take my left side as this, and the right side just
do a normal invocation. And this-- JAKE ARCHIBALD: Technically. SURMA: So the set
function kind of thinks it's being called on
store even though it is-- there is no tight coupling
between those two things. JAKE ARCHIBALD: Exactly. So you use this just as
you would in a class, and this will refer to the store
as it would within the class. And this can be tree shaking
and all of that stuff if you don't use it. SURMA: I've used this in
Babel a couple of times. But I don't think this
has shipped yet anywhere. JAKE ARCHIBALD: No,
and this makes me sad that it looks like the
whole proposal is dead. SURMA: Oh, that's sad. JAKE ARCHIBALD: That--
it does make me sad. SURMA: Do you know why? JAKE ARCHIBALD: Well,
because another proposal has started taking-- caught people's attention for
doing a lot of the same stuff. And this is the direction
that the RX folks have been looking at. So same again-- you
import the store and then separate methods. SURMA: Like same as before. JAKE ARCHIBALD: But-- [HUMS OMINOUSLY] SURMA: OK. JAKE ARCHIBALD: So this
is the pipeline operator. SURMA: What's the difference? JAKE ARCHIBALD: Well, so
what this is saying is coal-- they will take the right hand
side, treat it as a function, and pass the left hand
side to it, and call it. SURMA: So set right now it is
a function that you invoke, and it returns another function. JAKE ARCHIBALD: Yeah,
great, isn't it? So that's-- yes, so your
implementation of set would look like this. So here we go to a function,
which returns a function. The first one takes
the key and the value, and the second one
takes the store. SURMA: I see. The ugliness is
hidden, but it is ugly. JAKE ARCHIBALD: Yeah. Yeah. And this is the way the
RX folks are looking at-- I think it's OK. I think you're right-- writing it is confusing. Explain to someone that,
oh, yeah this is a function, and it returns a function. That's how it works. SURMA: So I think I've
seen this operated before-- the exact same
operator in F sharp. JAKE ARCHIBALD: Yes. SURMA: It works
differently there, though. Because there, basically,
what is on the left hand side will become the first
argument of the function of the right hand side. JAKE ARCHIBALD: So
in this case, it will become the first
argument, but it will be-- SURMA: But of the
function that it returns. JAKE ARCHIBALD: I see. SURMA: That would be injected
in front of the other argument. So you don't have the necessity
to create a new function first before you can start using this. JAKE ARCHIBALD: So there
is an alternate proposal, which looks like this. Here you're using
a question mark to say where a store
would be passed into. SURMA: I see. JAKE ARCHIBALD: And this
is the hack style of it. SURMA: So where's this at? Is this-- JAKE ARCHIBALD: So
this is stage 2. There are two main competing
proposals for the pipeline, and that spawned another
12C7 variants of the two ways of trying to combine the two. So that's, yeah, it's
very much experimental, still discussing
the features land. But I keep going back there. Yeah, I keep going
back to bind for things which are instance methods. And I feel like
even if this ships, I feel like I would end up going
for something more like this. SURMA: Oh, that's
actually not too bad. JAKE ARCHIBALD: Like where I
have a do method that takes-- SURMA: Legit just under
the hood, probably, switching it around right? JAKE ARCHIBALD: Which
are legitimately under the hood is
just going to do-- yeah, it's just going-- SURMA: It's going to do? JAKE ARCHIBALD: The
argument's this? Exactly that. SURMA: I like this
pattern, honestly, because this you can do today. And it would allow you
to do the tree shaking. JAKE ARCHIBALD: Exactly. The downside to this pattern
is I don't think it's possible with TypeScript, which I know
it shouldn't hold you back from JavaScript but if you're-- SURMA: Why not? JAKE ARCHIBALD: Because in the
do case, the second and third and to infinity
arguments, their types depend on the the thing
of the first argument. SURMA: You can do
that, but then the type would have to know about
all possible functions. JAKE ARCHIBALD: Exactly. SURMA: It's like they
do with event listeners where they define the type
depending on the string value of the first
argument and then define what the event type will be. JAKE ARCHIBALD: So you
can do that with a string. I don't know if you can
do it with an object. You maybe can. SURMA: Good question. I actually don't know. But it's definitely more
complicated than it should be. JAKE ARCHIBALD: So, yeah. So that's the problem
I have to say. That is probably the
best solution I've got or just a function, which will
take the store object and-- SURMA: Or just stable
the bind operator. JAKE ARCHIBALD: Or just
be able the bind operator. SURMA: It still ended up--
the plug in still exists. JAKE ARCHIBALD: Yeah, but to
go for something which is not going to be pursued
in JavaScript, maybe, it feels like the
wrong direction to go. I don't know. There's one more
proposal, which is just being talked about, which I-- it would be a way of
having an instance and a declarative way of
saying, take these extensions and apply it to this class
but only in this scope. SURMA: OK. JAKE ARCHIBALD: And so
it's a kind of way of-- SURMA: It's very specific
to this problem then, though, because I feel like-- JAKE ARCHIBALD: Absolutely. SURMA: Bind operator would be
a more powerful generic even-- or a better solution
of the pen operator would be more generic,
more powerful tool to have. JAKE ARCHIBALD: And that is-- yeah, that's my worry
about it as well. Is it solving that
specific problem whereas bind solves that problem
and lots of other problems? SURMA: Yeah. JAKE ARCHIBALD: So, yeah, I'm
curious to see where it goes. We've got hacks we can
use in the meantime. SURMA: Yeah. JAKE ARCHIBALD: But I just-- yeah. I want bind or a way to do
this in TypeScript, which might already be
possible, and if so, someone should tell
me in the comments. And this is me farming off
my work to other people. SURMA: [LAUGHS] Should
we introduced 0HTB codes? JAKE ARCHIBALD: [LAUGHS]
Negative HTB codes. SURMA: What if we reach 100? JAKE ARCHIBALD: Oh. SURMA: What do we do when
we actually shoot HB2 or 3?