In my last tutorial about the Polymer library, I explained how to take advantage of this great new tool to create reusable web components. The key point of the tutorial and of using components, is to help our development by:
- Encapsulating much of the complex code and structure
- Allowing developers to use a simple-to-use tag style naming convention
- Providing a suite of predefined UI elements to leverage and extend
I'm still smitten with it and wanted to explore this a little more by checking out a new template the Polymer team released to make deployment and reuse substantially easier.
The Canonical Path
One of the quirks of the Polymer development process which I didn't touch on, was the disconnect between developing a component and actually making it available for reuse by others. Let's take a look at a snippet from my previous tutorial:
<link rel="import" href="../bower_components/polymer/polymer.html">
This purpose of this code is to include Polymer core, the main API that allows you to define the custom elements. For local development and testing, this actually works perfectly but unfortunately the path specified will actually prevent you from sharing this component. The reason for this is because if another user tries to install your element with Bower (which is the preferred installation method), it's going to end up as a sibling of Polymer in their bower_components
folder.
The problem with that, is that the component is going to be looking for ../bower_components/polymer/polymer.html
which will be an invalid path. Components must always assume that their dependencies are siblings, so it should actually be looking for ../polymer/polymer.html
. This the "canonical path."
In chatting with the awesome Rob Dodson of the Polymer team, he said that the only way around this was to develop using the method I originally outlined and once I was ready to share my component, convert all of my paths that look for bower_components
over to ../
when I'm ready to publish my element.
This is obviously not ideal and I probably could've created some type of Grunt task to parse through my component files to make these updates. Thankfully, the Polymer team has been noodling on this and has come up with a creative solution that they call the untitled-element
.
The untitled-element
Template
When I mention untitled-element
, I'm referring to a new boilerplate that's available to make creating reusable and deployable components substantially easier, by giving you a base foundation to work with. It helps to eliminate the issues I mentioned above by:
- Providing guidance on proper directory structure
- Incorporating an additional component that serves to document your API
- Allowing you to easily demo your component during development and when sharing
The big win for this, is being able to develop your component without having to go through the trouble of making substantial path changes that are not only cumbersome, but could break your element if you miss something.
Currently, the project is a part of PolymerLabs as it gets put through its paces, but it's certainly looking pretty solid:
Now the first thing you're going to want to do is create a development directory that will house your new component, as well as all of the Bower components you'll install. I called mine polymerdev
. From there, you'll need to go to the untitled-element
Github repo and download it into your new development folder. This is an important step because you need to extract the contents into that folder, to avoid the sibling directory issues that I mentioned previously.
Extracting the .zip
file will create a new folder called untitled-element-master
which contains the boilerplate files you'll need to create your new component. You'll need to rename a couple of things based on the name of your component. This includes:
- The
untitled-element-master
folder untitled-element.html
untitled-element.css
I'm going to recreate the Reddit element that I created in my last tutorial, so this is what the changes would look like:
-
untitled-element-master
->reddit-element
-
untitled-element.html
->reddit-element.html
-
untitled-element.css
->reddit-element.css
Here's what the directory looked like before:
And here's what it looks like after the updates:
The key thing to understand, is that you'll be working inside of the reddit-element
folder when creating your component and in later steps, when we use Bower to install the Polymer components, that directory will be a direct sibling to the newly installed directories. I know I'm really harping on this point but it's an important thing to understand, since it affects your ability to share your component.
To finish this off, you're going to want to update the references to your component name, inside of the following files:
bower.json
demo.html
reddit-element.html
Each of these files contains references to untitled-element
within the code and need to be updated. Remember that any references to untitled-element
should be changed to reddit-element
. If you want to be absolutely sure, do a global search-and-replace using your editor.
Getting Setup for Bower
Since Bower is the preferred method for installing Polymer and sharing components, let's go through a few steps to ensure that we setup the Reddit component's Bower configuration properly.
By default, the boilerplate includes a bower.json
file. This file is used to list several things, including the name of the component and any dependencies that need to be installed to use it. Here's what it looks like:
{ "name": "reddit-element", "private": true, "dependencies": { "polymer": "Polymer/polymer#master" } }
First, I'll remove the private
property since it'll prevent the component from being listed in the Bower registry. Since it's supposed to be shareable, I want it to be listed. Also, the Reddit component needs to make an Ajax call, so I'm including a dependency on the Polymer core-elements
set of components which includes the Ajax functionality that I need. Lastly, I'll add a version number to track this going forward. Here's the end result:
{ "name": "reddit-element", "version": "0.0.1", "dependencies": { "polymer": "Polymer/polymer#~0.2.3", "core-elements": "Polymer/core-elements#~0.2.3", } }
The last bit of Bower configuration that needs to be done, is to create a file called .bowerrc
in the reddit-element
folder which defines a custom install location for the dependencies of our component. This is defined as simple JSON data like this:
{ "directory": "../" }
What this essentially does is tells Bower to install any dependencies one level up, so that they're siblings of the reddit-element
folder. The reason this is important is because when someone installs our component with Bower, it'll be placed into the bower_components
folder as siblings to everything else in there (including Polymer). Structuring things this way, ensures that we're developing in the same way that we'll eventually be sharing. It also allows us to use the canonical path I mentioned above, ensuring a consistent way of referencing other components in our code.
Let's review the differences. If I didn't create the .bowerrc
file and ran the bower install
command, my directory structure would look like this:
This installs the bower_components
folder directly into the component's directory, which is not what I want. I want the reddit-element
folder to be a sibling to all of the dependencies that it needs:
This method ensures that when a user installs this component using Bower, the component and the dependencies will be installed properly into the bower_components
folder.
With the .bowerrc
file added to your component's folder and the bower.json
setup with the proper dependencies, the next step is to run bower install
, to have Bower pull down the appropriate components and add them to the project.
Coming Up Next
In this tutorial, I wanted to make sure I laid a solid foundation for how to use the new Polymer boilerplate and some of the rationale behind the design choices that the team has made.
In the next part of this series, I'm going to go over the new documentation component that's included in the boilerplate and how it will make sharing and demoing your component substantially easier. I'll also show you how to setup your component to be shared via the Bower registry.
Comments