Polymer and Bower: Getting it Right

If you've started building Web Components with Polymer, you'll know that Bower is a critical part of the process. What you may not know is how to best structure your project to take full advantage of Bower.

Front-End Dependency Loading

While Bower allows you to declare dependencies, it doesn't do anything to actually help load those dependencies. Rather this is left to the discretion of the containing application. For instance, a plugin that depends on jQuery expects that jQuery has already been loaded.

For custom elements written with Polymer, things are a little different. Your custom element may depend on one or dozens of other custom elements, and asking the user to manually import each dependency destroys many of the gains of using Web Components to begin with. So when developing a reusable element, what can you do?

First Things First

First things first, you'll need to create the basic directory structure for your project and initialize a bower.json using bower init (or by hand). Your package name, folder name, and element-defining .html file should all share the same name. So if I made an element called my-element the structure would be:

my-element/
  my-element.html
  bower.json
  README.md

The bower.json might look something like this:

{
  "name": "my-element",
  "dependencies": {
    "polymer":"Polymer/polymer"
  }

Relative Import Paths

With how Bower works, you may not know the exact directory relative to the document root in which dependencies are installed. However, you do know that they are all installed in the same directory. This means that when importing dependent elements, you should do so using a relative import path to the parent directory. For our my-element example, that might look something like this:

<!-- in my-element.html -->
<link rel="import" href="../polymer/polymer.html">

<polymer-element name="my-element">
  <!-- ... -->
</polymer-element>

The .bowerrc Trick

As you work you'll quickly realize a problem: since your project depends on relative roots to sibling directories, if you run bower install in your project root it won't be much help. One way to work around this is to create a .bowerrc file in your project directory like this:

{"directory":"../"}

What just happened? We told Bower to install dependencies in the parent directory of the project, creating siblings just like we'd have if our element were installed as a dependency. So now if we need a new dependency, we can simply add it:

bower install --save Polymer/core-ajax

This will add to our bower.json but also install the package in the parent directory, meaning we'd easily be able to add core-ajax to our imports:

<link rel="import" href="../core-ajax/core-ajax.html">

Note: Because this trick affects the parent directory, I'd recommend you create a workspace for your custom elements that isn't mixed in with other projects you may be working on.

Good for You, Great for Others

If you follow these conventions it will make sharing and reusing your custom elements much easier.With a simple bower install --save my-element and a quick link tag your element will be up and running in no time!

To wrap up, here are some things to do (and avoid) when packaging up custom elements:

  • Do: Name your package, element, and .html file the same thing.
  • Do: Use relative paths e.g. ../polymer/polymer.html when importing other custom elements.
  • Do: Submit your work to customelements.io so that others can discover your awesomeness.
  • Avoid: Putting polymer.html into your project folder and depending on it locally.
  • Avoid: Using a polymer- prefix for your element name. Polymer elements are interoperable with other custom elements, so this is unnecessary!

At Divshot we're incredibly excited to see Web Components become a major part of the web development world. If you have any questions about Web Components, let us know below or hit us up on Twitter!