Transcript
This transcript was autogenerated. To make changes, submit a PR.
You.
Hello Comp 42 and welcome to my talk.
Build your next app with web components. My name is Andrew Desmarais.
You can find me on all the social medias at Teradocs. My website
is Teradocs tech and my background
is that I've been in the industry for about 17 years, started with building
back ends for the most part, but over the course of the last decade have
really strived to become a full stack engineer and worked with a
lot of different web technologies, which is what has led me to
the talk that you're hearing today about really trying to stick to the platform.
So what's the problem? The problem really stems
from the framework wars, the constant flame wars about
frameworks. And it really is my
opinion that every line of front end code is tech debt when it's written in
a framework. The most pressing example I
have of this is Angularjs.
When everyone was really early in the framework world,
Angularjs came on the scene and was the best thing that we had
available. It really sped up our ability to create web applications
quickly, and a lot of different companies latched onto it to build their
enterprise software. This has since yielded a major
problem. Angular JS was deprecated four
years ago, five years ago at this point, and as of December 31
of 2021, it will no longer be supported at all.
So that means that every application that was written in angular JS now must
be rewritten into something else, and I would encourage you to rewrite it
using web components.
Outside of that specific example, we've all lost sleep to the framework wars.
By choosing the right framework, you're always going to pick wrong because
there is no good choice in my opinion. But I also think that frameworks
equate to vendor lock in. Choosing a specific framework
means that everything you do is going to be built in that framework, and you're
not really going to have an opportunity to mix and match, very often without a
lot of overhead. There's also upgrade fatigue.
Like every time a framework upgrades, you really should be upgrading to
the latest and greatest because there are security patches that to address vulnerabilities and
there are new speed improvements in those frameworks that are being addressed.
But that comes with a major downside of all of the dependencies
that are bundled in with these frameworks that you're not in control of,
you don't get to control if viewer react includes a new dependency
that you're not in control of. And we've all seen some of the big
problems that can happen with large dependency trees.
With the breaking of the web in several cases, right thinking
left pad, or in the large vulnerability cases that we've
seen. So it's good to minimize our dependency tree
as much as possible. So that's why I encourage you to use our newest ally
that we have on the scene, web components. So I
want to dive into web components a little bit to explain what they are.
In case you're unfamiliar with them. It's important to understand
that they web components based, obviously components in the name.
They do come along with lifecycle methods though, so that's something that you're used to
in all of the frameworks. Web components have them too. They have great
style encapsulation built in just via the shadow Dom,
and they have some of the greatest documentation on the web with
MDN. MDN is supported and
curated by Mozilla and provides probably the best
curated documentation out there. So let's talk about web components.
What are they? Web components are a combination of
a few different pieces of web technology. I'm not going to cover
all these super in depth, but let's go over them really quickly.
So we have custom elements, which is basically the ability to define your
own HTML elements. We have the shadow Dom,
which is a way to encapsulate not only your CSS but also your HTML
and isolate them from the rest of the Dom. Then we have slots,
which is a way to allow your consumers to bring their own content
into your components. Think content projection in angular or children
in react or slots in view. And then there are
templates, which is just for faster render times. It allows some HTML
elements to be defined ahead of time and then cloned really quickly for use
later. So getting in a little bit deeper on custom elements,
they're pretty limited with the number of requirements that I have.
The only requirements really are that the tag name has to be all lowercase
and it must contain a hyphen. Outside of that you can kind of
name it whatever you want. Believe it or not, something as
obnoxious in my opinion, as t hyphen can actually
be a valid custom element name. I don't know why that's allowed,
but it is. So outside of that though, there's lifecycle methods.
Lifecycle methods for these elements consist of
connected callback, which is when an element is added to the DOM, disconnected callback
elements removed from the DOM, and when the attribute changed
callback, which is keeping track of when attributes are changing on
that element. So really feels familiar if you're used
to other frameworks with some of these lifecycle methods,
and also nice minimal requirements.
Thinking of style encapsulation, something that a lot of us have used different
systems to encapsulate our CSS. The shadow
DOM provides beautiful style encapsulation.
Effectively, the shadow Dom creates a miniature dom that is isolated
from what we call the light dom, which is the main documentary.
By using the shadow dom, when you put a style sheet into it, that style
sheet is actually isolated from the light dom and will not affect any other elements
except for what is in the shadow Dom. The benefit of this is that we
don't have to obfuscate our class names. We don't need build tooling that's going
to do that for us. We can use regular old class names.
Or if you're using really small amount of, very small amount of
HTML, you could just reference things by their tag names.
Because you're so tightly encapsulated, you don't have to worry about that
bleed of CSS, bleeding outside of that component and affecting
things you didn't intend. So super powerful to be able to have the shadow
Dom encapsulating your styles. The next one is
slots, and this allows components to really
take advantage of consumers providing their blown content. So the example that you
can see in front of you is a basic card component where I want
the consumer to tell me the title and the image and
the description of that image. And as long as the consumer provides
those things in the slots, then the card will render exactly as you would expect
it to. And you get all of this additional styling of
all of the elements that are being brought in and all of this additional layout
that the consumer didn't need to worry about because it's a component.
The last thing is documentation. So MDN
really is some of the best documentation we have
on the web. It's extremely well curated and it's kept
up to date in a much better fashion than a lot
of other documentation out there. So all of the things I've talked about so
far with web components are documented on MDM. I encourage
you to go out and look at it because all of their documentation is absolutely
fantastic. So one of the questions I get a
lot when I talk about this to people is, is it really
enterprise ready? And the answer is absolutely.
Like, how enterprise ready is it? Well, YouTube, as a great example,
is all web components. It's using web components for
everything that it does. And how do I know this?
Because of a beautiful piece of tooling called web component devtools,
which allows us to inspect and interact with web
components in a way that is a little bit harder if you're just using the
native chrome devtools gives us access to attributes
and properties and see the slots that are available and things like that.
You can see it's still fairly new, it's young in its development lifecycle,
but it is a pretty powerful set of tooling. It's also
nice to see that things like YouTube aren't alone. We also have the Nintendo Web
store, which is also based completely in web components. So if
Nintendo is betting their financial
gain on web components, you can bet that it's actually a
well baked, enterprise ready piece of technology.
So another question I get about is delivery. How are we delivering
web components? What does that story look like? The nice thing is, if you're writing
native ESM, you can actually just deliver your ESM directly to
the DOm using a script tag. And then your markup is, well, it's just
markup. Even with your custom elements, that markup is
really readable and really maintainable because it is just HTML
at the end of the day. So beautiful that web
components provide such a simple delivery system.
But what if I want minification and bundling and those types of things that my
framework provides me? Well, we still have all of the bundling tools available to
us. I've chosen to highlight webpack and roll up here if we want minification.
These are the two examples that provide minification for you. So webpack
gives you nine whopping lines of
config that provide you with minification and
a basic minified bundle. And then the same thing in roll up,
a little bit bigger, but only 13 lines to give you that nice ESM
bundle with minification using terser. But very,
very small amount of work needed to be able to get some of that basic
minification that we're used to. And then I wanted
to rehighlight the fact that this is really just a script tag.
Like how simple is it? It really is this simple. This is the entire HTML
document to demonstrate that card example from earlier.
So that one script tag comes in and that card
HTML is just HTML. So it's super powerful to
have something so simple to look at and read because it creates
a high level of maintainability in the long run. The other
question that I get is support. Is it really well supported?
Yeah, it's extremely well supported. All the major
modern browsers support it. And if you really need ie
eleven support, there are polyfills out there for that too.
So it is extremely well supported out there in the industry.
And you know how I was talking about upgrade fatigue earlier.
The nice piece is the browsers maintain the
upgrade for you if something needs to be patched. From a security vulnerability perspective,
the platform is going to patch it. If there is a new
piece of functionality that needs to be released, the platform is going to release it.
So it makes life really really easy to maintain.
So let's talk about a lot of the common things that frameworks provide
that we're going to need if we're going to build an application with web components,
things like dynamic templates and data binding and routing,
and bringing along our favorite CSS library that we want,
and state management. Because all of these are questions that we need to answer if
we're going to be convincing the people around us that we can do this thing
with web components. So dynamic templates,
it's just JavaScript at the end of the day. So using basic
string concatenation we can get through with 99%
of what we really want to accomplish.
And that means that string template literals
have kind of become the way to go. Using backticks allows
us to define string template literals in a way that we can drop in the
variables that we need to at the time that we need to. But if you
really want some advanced rendering, we can go with a really thin and small
library, something like lid HTML. If six k is
too big for you, there's also things out there like micro HTML or UHTML
that are even smaller at two k that provide most of the things that lit
HTML also provides. But if you bring in lit,
then you get dynamic template rendering, you get data binding, you get
event binding, attribute binding, property binding, et cetera. And for
a very very small bundle,
data binding. Well the nice thing is that web components
are just objects, just like everything else in JavaScript. So if you can grab
a handle to it using a query selector, then you can just pass in
complex data objects by passing them to a property on that tag.
So documenting that is definitely a big deal, but it's also
not that big, not that hard a thing to do as you're developing your web
components. And once again, if you really want something that
feels a little bit more fluent and a little bit more native, then you can
use lit HTML to do that. Property binding in line routing
is the next biggest one. People are so used to routing having to
be something that is very very framework specific.
But luckily there's a set of framework utilities out
there, a set of UI utilities out there, sorry, called Vodin.
And Vodin has a router that's a standalone router, you don't have to bring it
along any of their other UI components. And that router gives you
a lot of the features that you're used to getting with a framework. Things like
child routes and fallback routes, and being able to grab route
parameters and use those in your templates also handles redirects so
that if you're upgrading a path away from one path to a new path,
you can handle that. And one of the biggest features that frameworks tend to provide
us is the lazy loading of JavaScript bundles. The Vodin
router handles the fact that you don't need to load all of your JavaScript
up from if you have a bundle of web components that aren't used on the
first page and are only used on a second page of a wizard system,
for example, then don't load that up from bundle
that separately, load it separately, and Vaden's router will allow you to load
that lazily as that navigation is happening.
So bringing in SAS or less I'm choosing SAS
in this example. Bringing in know going
with a bundler is pretty much the only way that you're going to be able
to do that. You need some build step to accomplish it, and with the shadow
dom in play you're going to have to be able to import those things.
So on the left is webpack. Not the
smallest amount of config in the world, I will admit, but at the same time
it's also not that complex. It uses both the SAS loader and the raw loader
to be able to bring that in. And this allows us to import that
style sheet like text so that when I'm importing it from within
my component, I can actually just take the text from that SAS file
and put it inside of a style tag and it will render appropriately to
get that same functionality out of roll up. It's much simpler because
of the SAS rollup plugin. Simply setting output to false on
the SAS rollup plugin means that it will output text to the import and
that allows us to use it exactly like we would want to.
State management is the last big one. So how do
we handle state management? I really like to keep the
kiss principle in mind, keep it super simple.
Keeping it super simple means don't overcomplicate
things because they feel like they are complicated.
State management can be kept very simple. As an example,
one of the ways that I like to keep state management simple for my applications
is I use singletons. If I have a user that
could appear somewhere in the application and it could appear in many different places,
then having a singleton class, which is effectively a class that only is
ever instantiated once, but can be fetched many times. Having that
Singleton class manage the state for that user means that I can reference
it anywhere in my application, but it's only held in one place
in memory. I don't have to worry about fetching it multiple times or
how to do caching that can be handled by the Singleton service that I've created.
If you are growing really, really large and you have a lot of state to
manage, you can always go redux. Redux is just Javascript
at the end of the day, but I found that to be overkill in the
vast majority of cases. And the last one is if you're using GraphQL,
you can always use Apollo for that. Apollo has a lot of good caching and
state management built into it that will help you out if you're using graphQl.
So thank you very much for taking the time to hear me out on
this web components thing. I hope that I've opened your eyes a little bit
to what's available to you out there, and I really hope that
if you're given an opportunity to in the future that you'll choose
web components as your way to build your next application. Thank you.