Bower Shim Maintenance
This is one example of making Ember add-on using a Bower shim maintenance workflow. A Bower shim is basically a wrapper for some arbitrary set of files you want to become available in
bower_components in a client application's project folders.
ember-cli generator, developers can now easily add Bower dependencies to Ember projects via a call to
addBowerPackageToProject in an
afterInstall hook. More on this later.
With a Bower dependency being available and bundled, you can, say in Ember, do:
Say you've got a project,
target and you love it. You want it to be an Ember add-on. However, you're not the maintainer of the actual
target project, but a contributor (via fork, etc.). Instead, you're a loving bystander, anxious to help the larger community to use
ember-cli-based project, you want to be able to just chuck this dependency in. But there are hurdles. In order for this
target package to get cannonized into community usage, you need it to be installable via Bower, and in turn
target must have a shim available as an
Not very tall hurdles, mind you. But hurdles nonetheless. You need a plan.
For purposes of example, let's use
Ember.ListView as a
If you build it
target project ought to, as any good project does, manage its own build procedure. Maybe this involves running an
npm run [...] task, something with
grunt, or some such build procedure resulting with a set of shiny files in a
/dist directory. Usually...
git clone [the target repo]
cd [target dir]
[build, e.g. npm run build-all, grunt build:production, etc]
This last part is wildly variable depending on the project, so, going with
Ember.ListView, we'd do:
git clone https://github.com/emberjs/list-view.git
npm run build-all
Once the build procedure completes, you've got a nice set of files in
Now your part
A Bower shim is most easily created in a two-part fashion using a "bundle" and a "shim" pair of git repos. The way I set this up for
Ember.ListView was by creating two git repositories: one for the built distribution, the other for the
npm installable package.
I created a git repository called ember-list-view-component to host the actual valuable files a user will want to import into an application project. This is not a project that a user of the shim will know anything about. This is here for the purpose of Bower to know where to get its package.
I created a git repository called ember-cli-list-view to host the
npm installable package. For example, the first step in getting the
Ember.ListView package into your project would be to add this as a dependency:
npm install ember-cli-list-view --save-dev
However, let's not get ahead of ourselves.
- component name: ember-cli-list-view
- component repo: .../ember-list-view-component.git
Since you've easily created a distribution set of your
target project using its own on-board build strategy, and you have a fine set of files to bundle up, first create your git repository (beyond the scope of this article).
The contents of my repository, or
component, are like:
bower.json file should follow the standard specification for Bower projects. Refer to the bower.json-spec for details. It's a file you need for the
component to work with the
bower command line interface when installing as a dependency.
The other files are all rather arbitrary as to what you should include. For my purpose, I've included the
list-view* files, a
README.md to clarify things to consumers, a
LICENSE, and a
.gitignore file to make commits less clumsy.
Once you've successfully committed and pushed your code to the repository and have your
component sitting there at version
0.0.1, you've taken a huge step.
If all you're doing is creating a Bower component, just follow the "Register" steps to add your repository to Bower's package registry. However, since we're in the business of creating an Ember add-on, there are some things not to do.
I want users to access this
component using the typical
ember-cli-* namespace convention, so will give it the name
ember-cli-list-view. Note: This can cause confusion when it comes to naming the
shim shortly, since it will be called
As far as creating a Bower dependency, you're pretty much all done. Now you should be able to run
bower install <my-package-name> in any directory and have your
component available in a
- shim name: ember-cli-list-view
- shim repo: .../ember-cli-list-view.git
In order to make your
component installable via
npm (as Ember add-ons are typically done), another step is required. You want Ember devs to be able do run:
npm install <your-package> --save-dev
ember generate <your-package>
Under the hood, the
ember-cli generator uses a blueprint to execute some code or move some files or whatever. Thanks to the excellent enhancement a la @rwjblue, #1830, this is now pretty simple to install Bower dependencies using the
I created a second repository with these contents:
For a look at what's inside (particularly the blueprint file), take a look at the repository on Github. The blueprint's index file is where the
addBowerPackageToProject call is made in the
Once the git repository is committed and a shiny new version
0.0.1 package is available, it is required that the package become registered with npmjs.org. Here are some useful resources:
... and go!
With the shim and component available via Github, npmjs.org, and Bower.io, the work of installing an Ember add-on is just a tag-game away.
Tag, you're it
So while you've published your NPM package, the
target project has continued on with development, adding new features, fixing bugs, optimizing for performance, etc. At some point, you'll need to bring those changes into your
shim are Bower and NPM (respectively) pointers to git repositories, tagging is the essential way for marking these packages for release and/or update.
Working with tags can seem tricky at first, but the premise is simple. Like any version control system branching and tagging are at the core of "labeling" your varying efforts. While a branch hosts development efforts off of the master branch, a tag is simply a marker (either on the master branch or a development branch) that says "at this point, this code is
Using a tag, your consumers can do:
npm install <your-package>@<tag>
The NPM and Bower systems require semver versioning, and enable easy updating using a
version command, e.g. in your project directory, you can simply do:
[bower|npm] version [<newversion> | major | minor | patch]
The version command also will update your git repository on the fly. From the docs on
npm version here:
If run in a git repo, it will also create a version commit and tag, and fail if the repo is not clean.
The same exact phrasing conspicuously appears in the API documentation for
bower version here. Since you're doing this work in a git repo, you can rest assured that your git tagging is handled with this command.
Version tagging a la git
Skip this if you're doing shim maintenance since the
npm|bower version commands automatically create (or are supposed to create) git tags for you. Just remember to do the
git push --tags thing after using one of these other registries to bump your version.
However, if you are just trying to tag a version in your git repo (without regard to Bower or NPM), once you've made all your changes and are sure you want "this" version of the code to be a release version, you need to add a git tag. Tags should follow semver, and start with "v". In your project directory do:
git tag -a v0.0.2 -m 'Update `target` to latest'
git push --tags
v0.0.2 assumes this is, say, your first update because your first version should have been
Bump an NPM package version
See the docs on versioning NPM packages.
Note: Currently I'm having trouble with
npm at version v0.11.14. Using a prior version, e.g. v0.10.33, seems to be okay.
cd [target package]
npm version patch -m 'Bumping version to s%'
git push --tags
npm tag [target package]@[new given version] latest
The order matters here.
Remember, this repo hosts your shim, not your component. In order to update your component, you'll need to bump the bower version also.
Bump a Bower package version
See the docs on versioning Bower packages.
cd [target package]
bower version patch
git push --tags
And that's all there is to it. Just kidding... this is a really convoluted Rube Goldberg system and should be much easier to deal with. The fact that front end developers are beholden to both NPM and Bower to maintain dependenices is pretty much wrong. We should just be using NPM for this. I is unclear to me why Bower even needed to happen when NPM is doing a perfectly suitable job of managing dependencies -- both server- and client- side.
Hit @isaacs with suggestions if you have ideas that can help make NPM better with client-side dependencies.