CanJS makes it easy to make better apps, faster. But, what about making a better CanJS faster?
Two weeks ago, the CanJS core team spent time improving our CanJS dev/test/build/doc infrastructure to make it easier to add new features faster.
One of the most difficult challenges in making improvements to a library is dealing with breaking changes. We want people using CanJS and to keep using it.
Most people understand that APIs change, but they hate it when it happens unexpectedly. We've taken the following steps to strengthen backwards compatibility without slowing down active development.
CanJS will now strictly follow semantic versioning. Our declared API is what is
documented on CanJS.com. Methods that are not documented should be considered unsafe. For example, there's a can.Mustache.get
method, but it's not documented, so don't rely on it.
Semantic versioning means you can upgrade CanJS 2.0.5 to any 2.X release. When 2.1 comes out, you will be able to upgrade without problem. In fact, you'll be able to upgrade 2.0.5 to anything less than 3.0.
Maintaining CanJS's 700 tests is hard work. When we deprecate an old API, we typically update all tests to use the new API. For example, if can.view.mustache
becomes can.mustache
, we replace can.view.mustache
in tests like:
test("trailing text", function () {
can.view.mustache("count", "There are {{ length }} todos")
var div = document.createElement('div');
div.appendChild(can.view("count", new can.List([{}, {}])));
ok(/There are 2 todos/.test(div.innerHTML), "got all text");
});
with:
test("trailing text", function () {
var template = can.mustache( "There are {{ length }} todos")
var div = document.createElement('div');
div.appendChild( template( new can.List([{}, {}]) ) );
ok(/There are 2 todos/.test(div.innerHTML), "got all text");
});
But after the change, we are no longer testing the deprecated API. We could easily break our promise of semantic versioning.
To make that unavoidable, we made it possible (and easy) to run new releases against old release's tests. In master, we've checked in 2.0.5's tests. Now checking new versions against old tests is as easy as running:
grunt test:compatibility
Starting with 2.0.5, you can download a development version of CanJS that gives warnings about deprecated API changes and common errors. For example, if a template finds something that looks like a custom element, but there is no can.Component for it like:
can.Component.extend({
tag: "my-tabs",
scope: { ... }
})
var template = can.view.mustache("<my-tab></my-tab>");
The console will warn you with:
can/view/scanner.js: No custom element found for my-tab.
We'll be adding more warnings in future versions. Let us know other useful warnings and messages by submitting an issue similar to this.
A better CanJS means getting out new features faster. Traditionally, we experiment with new features at Bitovi prior to releasing them in production. But this means only about 20 people are using these features.
Going forward, we are maintaining a minor branch with the tested and document features for the next minor release.
Currently, the minor branch represents 2.1.0-pre
. It includes:
- "attributes" events
- can.view.tag and can.view.attr template hooks
- List deferred methods
- Deprecating can.Model.models and .model in favor of can.Model.parseModels and .parseModel
- can.Mustache performance improvements
And because we are testing against old versions, 2.1.0-pre
is backwards compatible with 2.0.5
. You can use it
in near-production environments.
We hope that teams wanting these new features will develop against the minor branch and pre-releases. This will help us perfect and harden the API earlier, which allows us to add new features faster.
Download 2.1.0-pre
here.
You can now easily switch between documentation for past, current, and future releases.
We've also started adding version numbers to signatures:
And deprecation warnings:
CanJS is now linted:
And docco is back:
It's our hope that these changes will help us release better features more often. We've got a bright roadmap ahead. Help us get there by using the pre
releases, submitting bugs, and implementing features.
Thanks!
Re:
Semantic versioning means you can upgrade CanJS 2.0.5 to any 2.X release. When 2.1 comes out, you will be able to upgrade without problem.
Is that intended to be 2.0.5 to any 2.0.x release? Or are we supporting 2.0.x APIs all the way up to anything < 3.0?