I work on a library called Polymer, which helps you write web components faster and easier. This is awesome, but itās only awesome if you (yes, YOU) know what a web component is, and know that you want to write one. So hereās a story about what these things are and teaches you how to use them without showing you 10 pages of docs and getting you to install tools and CLIs. Maybe itās for you. Maybe it isnāt. In either case, it has otters.
- Why should you care?
- Thinking about your app
- Where do web components live?
- Polyfills and you
- 1. I want to use someone elseās web component in my app
- 2. I want to write a web component to use in my app
- Thatās all there is!
Why should you care?
Web components arenāt a new library or framework, theyāre a new browser feature, and they let you write encapsulated and reusable components (more details). If youāve ever used an <input>
element, I like to think of it as the OG web component, because itās exactly that. The thing
is that before web components came around, you had to wait on all browsers
to agree on a new element (like, a date picker). And even after they agreed
on a new element, it took them yeaaaaars to implement it. <input type="date">
was drafted in 2011 ā today, 6 years later, not all browsers
have implemented it! With
web components, web developers get to write such elements, so that you donāt
have to wait for 10 years before all browsers agree that they should implement a date picker.
P cool, right?
- A component is a bunch of code that fits logically together, kinda like a unit of functionality. This could be a simple widget like a fancy button or a date picker, or a more complex UI setup like āa responsive blog layoutā
- Encapsulated means that an elementās styles and children are scoped to itself, so you canāt accidentally break what it looks like by using CSS haphazardly in your app
- Reusable means that if you have a web component, no matter how you wrote it, you should be able to use it in any other app, regardless of how itās built (eg, a React app). This is different than, say, a React component, which you canāt just use in an Angular app without bringing all of React with you (and in most cases, it wonāt even work)
- Using other peopleās web components is nice because it means you get to write less code, and you can use someone elseās code. Also, when I say āusing web componentsā, I literally mean
writing something like
<emoji-picker></emoji-picker>
, that just works out of the box. Remember, a custom element is just an open source<input>
ā whatever you can do with<input>
you could do with a custom element. - Writing your own web component is nice because splitting your app in smaller pieces makes it more manageable. Sharing your own web component with others means that they could write less code and use yours! Sharing is caring <3
- Using other peopleās web components is nice because it means you get to write less code, and you can use someone elseās code. Also, when I say āusing web componentsā, I literally mean
writing something like
You write web components in ES6 JavaScript. Polymer is a JavaScript library thatās like jQuery for web components ā you import it, it gives you a bunch of helper functions and saves you writing a lot of boilerplate code.
Also, bad habit: people (and me, I am those people) tend to use ācustom elementā and āweb componentā interchangeably. If youāre pedantic, they mean different things. Donāt be pedantic, it makes the otters sad.
Thinking about your app
If youāre starting to think about using web components in your app, thereās basically 2 situations you could be in, and I tend to reason about each differently
- I want to use someone elseās web component in my app
- I want to write a web component to use in my app
Thereās other things that you might eventually care about, such as making your application production ready, and improving its performance. They are super important topics, but if youāve never used a web component before, theyāre also not the most important topics for you right now.
Where do web components live?
Web components tend to have dependencies on other web components, so you need a package manager to herd all them cats. Most of the web components out there use bower
. Another popular one is npm ā you could think of npm
as a package manager for your server code and bower
for your client, and it wouldnāt be entirely incorrect.
The reason why you need a package manager and not just ādownload this element in a zip fileā is that unless that element is really simple, it might have dependencies, and theyāll have dependencies, and thatās a thing for machines and not otters. If you really donāt want to use bower
, then youāll have to sort out flattening your dependency tree on your own using something like webpack
. This is not the tutorial for you.
If you look up bower
on the web youāll hear things like ābut bower is deprecated nowā (which is true, but itās also been unmaintained for like a year and it worked fine, so nothing is really new on that front) and ābut why not npmā (because you can only have one version of the same web component in your app, and thatās hard if your dependency tree is not flat. You probably donāt actually care this).
To install bower
, a package manager, you must first install npm
, a package manager. Take a moment for a concerned sigh, but install it anyway. Upshot: I promise this is the only tool I will ask you to install.
If you want to find otter web components, WebComponents.org is a universal catalog of web components (but not a package manager, because that would be cray). Go check it out.
Polyfills and you
Not all browsers implement features at the same rate, which means while youāre waiting for them to catch up, you need to care about polyfills. Fun fact: you know how when you have a hole in a wall, you have to put spackling paste in it to make the wall look like a wall again? Polyfilla is a brand of spackling, and thatās exactly what a polyfill is ā it fills a hole in the browser, so that it looks even from the outside.
You have two choices:
- Ignore polyfills for now and just use Chrome to test your app, but know itās going to be hella broken on other browsers
- Care about polyfills, and include the polyfill in your app. Spoilers: itās just a
<script src="some-path/webcomponents-lite.js"></script>
include.
in your applicationsās <head>
tag
1. I want to use someone elseās web component in my app
Ok cool, so here we are. You have a web site, and you want to use someone elseās web widget in it. Letās say that thing is paper-button which is a super fancy looking Material Design button. Itās beauty and itās grace, itās Miss United States.
Here is a glitch app if you want to follow along at home. Glitch is an online code editor, where you can build apps and modify other peopleās ā which is why itās great for this example!
We need to do 3 things:
1. Install the web component
-
We do this by adding a
dependency
to ourbower.json
file. If you donāt already have abower.json
file (who can blame you), create one by runningbower init
, and answering the wizardās questions. They kind of look like this, though, spoiler alert: thereās no actual wizard š - To add
paper-button
as a dependency, you can either runbower install --save PolymerElements/paper-button#^2.0.0
or by manually adding it to thebower.json
file in itsdependencies
section:"dependencies": { "paper-button": "PolymerElements/paper-button#^2.0.0" }
- Because I promised you no magic:
^2.0.0
just means āthe latest version between 2.0.0 to 3.0.0ā. The reason I picked that version is that itās the latest one. - If you manually added the element to
bower.json
, you need to actually install it, so runbower install
.
Status check
Right now you should have a bower_components
folder created, that contains a whole bunch of folders, one of which is called paper-button
.
2. Import it in the app
This basically tells the browser where to find the definition for what this paper-button
tag is.
Much like how you import a CSS stylesheet with
<link rel="stylesheet" href="/style.css">
You import a web component with an HTML import:
<link rel="import" href="/bower_components/paper-button/paper-button.html">
3. Insert it somewhere in the app
Drop a <paper-button>Click me</paper-button>
somewhere in your html page.
Status check
Your index.html
should basically look like this:
<!DOCTYPE html>
<html>
<head>
<!-- Load the polyfill so that the demo works everywhere -->
<script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
<!-- Import the custom element so that the browser knows what it means -->
<link rel="import" href="/bower_components/paper-button/paper-button.html">
</head>
<body>
<h1>Oh, hi there</h1>
<p>Have you seen this fancy button?</p>
<!-- Use the custom element! -->
<paper-button>Click me</paper-button>
</body>
</html>
See that line about loading the webcomponents-lite
polyfill? Thatās the bit
that makes the demo work in browsers that donāt have web components yet š.
If you want to see what your app looks like without the polyfill, just comment
out that line and open your app in something like Firefox! Itās a good thing
to try out.
If we run that demo, it should look like this, plus or minus some copy and styles that Iāve added:
Now, say it together with the otters!
You could, of course, add JavaScript to that custom element, like you would
with any other <button>
or <input>
. I couldāve added something like this:
document.querySelector('paper-button').addEventListener('click', function() {
alert('you did a click!');
});
2. I want to write a web component to use in my app
Now that we know how to import someone elseās custom element, letās write our own! Up until now we havenāt actually talked about Polymer at all. You can totally write web components without Polymer; youāll just have to write a lot more boilerplate, and I donāt want that to turn you off web components.
The Polymer site actually has an awesome getting started tutorial, if youād rather read that. But while I have you here, youāll get the otter way.
In Polymer, every custom element is like a taco (bear with me). Thereās something called a dom-module
(which is actually a custom element itself) that holds 2 things in it:
- the
<template>
, or what your element looks like (html and css). A<template>
is an HTML element thatās inert ā when the browser sees it, it skips it and doesnāt render it - a
<script>
, which is what your element does
Sidebar: This is one of the advantages of using Polymer ā without Polymer, youād have to construct all your HTML and CSS in JavaScript, and somehow add it to your custom element. Polymer makes it easier for you to point at an implementation, and at a bunch of HTML/CSS and say āthat look goes with that codeā.
We add all our code to an .html
file (because remember: weāre going to do an HTML import to bring it in our app later). It ends up looking like this:
<dom-module id="my-element">
<template>
<!-- Any CSS your element needs for styling -->
<style>
/* This is a special selector that styles the element itself */
:host { ... }
/* Use the usual CSS selectors for its children */
p { color: tomato; }
</style>
<!-- that <p> style there applies here -->
<p>I should be a nice red!</p>
</template>
<script>
// Every custom element is an ES6 class.
// This is the implementation of the element.
class MyElement extends Polymer.Element {
...
}
// Every custom element needs to be registered.
// This tells the browser that the <happy-thing>
// tag uses _this_ implementation.
customElements.define(MyElement.is, MyElement);
</script>
</dom-module>
I tend to put one element per html
file, and then name the file after the tag of the element,
so I can keep track of it. I would save that into a my-element.html
file, and then import it in our app, just as before with:
<link rel="import" href="my-element.html">
Now, what goes inside your custom element is really up to you. The way I write elements is
- by either knowing ahead of time what that element should do (āI need an emoji-picker, so it should be a text field with a button and when you click on that button, you get a list of emojiā),
- or I am working on the app, and at some point thereās just too much HTML/CSS in the same place that looks like it can just be modularized away (āoh, all this code just deals with writing a tweet, it should probably just go into a
<new-tweet>
elementā)
As a slightly more complicated example, I made a <happy-thing>
element in this
glitch app (check out the
code). It basically takes whatever content you give to it, and when you hover over, it does a little shimmy animation:
I also made that element with plain JavaScript, without Polymer, if you want to compare it. Youāll notice the second example has a lot more boilerplate code,
which Polymer abstracted out for you.
Thatās all there is!
I hope this helped! Iām going to write another post in more detail about actually getting started with Polymer, and what kind of things you can do with it soon! In the meantime, hereās some other links to get you going:
- Google developers blog post on custom elements
- The Polymer getting started tutorial
- The Polymer quick tour of features
- A Polymer cheat sheet
- The Polymer docs