Skip to content

Commit

Permalink
Clean up the migration guide
Browse files Browse the repository at this point in the history
  • Loading branch information
chasenlehara committed Dec 19, 2016
1 parent f5d0578 commit bb2dc7a
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 70 deletions.
131 changes: 62 additions & 69 deletions docs/can-guides/commitment/migrating_to_3.0.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,39 @@
@page migrate-3 Migrating to 3.0
@page migrate-3 Migrating to CanJS 3
@parent guides/commitment 2
@templateRender <% %>

@body

CanJS 3.0 introduces a new even more modular project structure and several new features, while having a minimal number of deprecations or removals to the existing 2.3 API.
CanJS 3 introduces an even more modular project structure and several new features, while having a minimal number of deprecations and removals from the [2.3 API](//v2.canjs.com/docs/).

This guide goes over:

* How to install CanJS 3.0 and how that differs from in the past.
* The *minimal migration path*. The steps that are required in order to upgrade from 2.x to 3.0 with the fewest number of code changes.
* A second migration path with more modern conventions (such as the use of NPM packages).
* The future proof path using all of the modern libraries we are most excited about (such as [can-define]).
* [The *minimal migration path*](#Minimalmigrationpath), which includes the fewest changes required to upgrade from 2.x to 3.x.
* [The *modernized migration path*](#Modernizedmigrationpath), which includes upgrading your code to match more modern conventions (such as using the new npm packages).
* [The *future-proof path*](#Future_proofmigrationpath), which uses all of the modern libraries we are most excited about (such as [can-define]).

## Getting CanJS 3.0

The recommended way to install CanJS 3.0 is through [npm](https://www.npmjs.com/). If you are already using the [can package](https://www.npmjs.com/package/can) you can continue to do so, but we recommend installing the specific dependencies that you need.
## Minimal migration path

### Using can
If you are already using `can` through npm, simply run the following command to install the latest version:

If you haven’t installed CanJS through npm in the past please skip to the next section and install the can-* packages.
```
npm install can --save
```

If you are already using `can` through npm just change the version in your `package.json` to 3.0:
This will update your `package.json` to look something like this:

```js
{
...
"dependencies": {
"can": "^3.0.0"
"can": "^<%canjs.package.version%>"
}
}
```

Using the *^* ensures you get minor and patch releases as those are released.

### Using can-*

Better than installing the `can` package is to install just the packages that you are using in your application. For example, if you are using [can-component] you can install it with:

```js
npm install can-component --save
```

A full list of the available packages are shown the [homepage](http://canjs.github.io/canjs/).

## Minimal migration path
The `^` ensures you get minor and patch releases as those are released.

At minimum, to upgrade to 3.0, you must make all of the below changes to your code:
At a minimum, to upgrade your code for CanJS 3, you must make all of the following changes to your code:

### Use can/legacy

Expand All @@ -55,16 +43,16 @@ In your code where you normally would import `can`, instead import `can/legacy`:
var can = require("can/legacy");
```

This will give you a `can` object with *most* of the same APIs as in 2.3 with the exception of:
This will give you a `can` object with *most* of the same APIs as in 2.3, with a few exceptions:

* [can-mustache] is not included with can/legacy but can still be installed as a separate package.
* The former `can.view` functionality no longer exists, see below.
* [can.mustache](v2.canjs.com/docs/can.mustache.html) is not included with `can/legacy`, but it can still be installed as a [separate package](https://www.npmjs.com/package/can-mustache).
* The former `can.view` functionality no longer exists; see below for more details.

### Set leakScope on Components

In CanJS 2.2 we introduced [can-component.prototype.leakScope leakScope: false] as a property on a [can-component]. This prevents values in parent templates from leaking into your Component’s template. In 3.0 **leakScope** is now false by default.
CanJS 2.2 introduced [can-component.prototype.leakScope leakScope: false] as a property on a [can-component]. This prevents values in parent templates from leaking into your component’s template. In CanJS 3, **leakScope** is now `false` by default.

If you have a [can-component.prototype.template] like:
If you have a template like:

```
<some-component></some-component>
Expand All @@ -78,30 +66,30 @@ render(new Map({
}));
```

This `page` property is not available within some-component’s own template.
This `page` property is not available within `some-component`’s own template.

If the component’s template looks like:

```
<h1>Hello {{page}}</h1>
```

It can only lookup the `page` property on some-component’s own [can-component.prototype.ViewModel]. To restore the behavior in 2.x, simply set [can-component.prototype.leakScope] to be `true` on the component:
It can only lookup the `page` property on `some-component`’s own [can-component.prototype.ViewModel]. To restore the behavior in 2.x, simply set [can-component.prototype.leakScope] to be `true` on the component:

```js
Component.extend({
tag: "some-component",
ViewModel: ...,

leakScope: true
});
```
@highlight 4

### Asynchronous inserted/removed events

In your [can-component]s, the [can-util/dom/events/inserted/inserted inserted] and [can-util/dom/events/removed/removed] events were previously fired synchronously as the element was inserted into the DOM. To improve performance these events are now fired async.
In your [can-component]s, the [can-util/dom/events/inserted/inserted inserted] and [can-util/dom/events/removed/removed] events were previously fired synchronously as the element was inserted or removed from the DOM. To improve performance, these events are now fired asynchronously.

There is now a [can-component/beforeremove] event that fires synchronously in case you need to perform memory cleanup. For example you might need to access the parent’s viewModel:
There is now a [can-component/beforeremove] event that fires synchronously in case you need to perform memory cleanup. For example, you might need to access the parent’s viewModel:

```js
Component.extend({
Expand All @@ -117,7 +105,9 @@ Component.extend({
### can.view is no more
The `can.view` methods have been removed in 3.0. The most common use was to create a template renderer from a script element with the page. Instead of:
The `can.view` methods have been removed in CanJS 3. The most common use was to create a template renderer from a script element within the page.
Instead of:
```js
var render = can.view('some-id');
Expand All @@ -141,21 +131,22 @@ stache.registerPartial("some-id", renderer);
Native [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) are used instead of jQuery promises which means you need to:
* Include a Promise polyfill if targeting browsers that do not have native support. [Steal](http://stealjs.com/) includes a polyfill for you.
* Instead of `.fail()` use `.catch()`.
* Instead of `.done()` use `.then()`.
* Only a single a value is returned from a native Promise.
* Use `.catch()` instead of `.fail()`.
* Use `.then()` instead of `.done()`.
### Passing the "this" value within each helper
Note that only a single value is returned from a native Promise.
When passing the `this` value to a [can-stache.Helpers helper] like:
### Passing the `this` value to a helper
[can-stache] now passes a [can-compute] to [can-stache.Helpers helpers].
If you were passing the `this` value to a helper like so:
```
{{helper .}}
```
in [can-stache] this now passes a [can-compute] to the helper.
You can fix this either by having your helpers handle computes, or using [can-stache/expressions/call call expressions] instead:
You can fix this either by having your helpers handle computes, or by using [can-stache/expressions/call call expressions] instead:
```
{{helper(.)}}
Expand All @@ -169,19 +160,19 @@ Most recently-built applications do not depend on adding to the global namespace
Construct.extend("foo.bar", ...)
```
Which sets `window.foo.bar`, this argument is no longer accepted by [can-construct]. If you *really* need to set a global you can do so yourself using the return value of [can-construct.extend].
Which sets `window.foo.bar`, this argument is no longer accepted by [can-construct]. If you *really* need to set a global, you can do so yourself using the return value of [can-construct.extend].
Instead the first argument to [can-construct.extend] is the name of the constructor function. This is nice for development as you’ll get named objects in your dev tools.
Instead, the first argument to [can-construct.extend] is the name of the constructor function. This is nice for development as you’ll get named objects in your dev tools.
## Modernized migration path
In addition to the above, to set your project up to more easily be able to upgrade in the future you can take the following measures:
In addition to the above, take the following measures to set your project up for easier upgrades in the future:
### Use can-* packages
As mentioned earlier in the guide, CanJS 3.0 is divided into separate npm packages. This allows us to more quickly updating parts of CanJS without affecting other functionality. You can take advantage of this by installing the individual can-* packages and using them directly.
CanJS 3 is divided into separate npm packages. This allows us to more quickly update parts of CanJS without affecting other functionality. You can take advantage of this by installing the individual can-* packages and using them directly.
You might be using [can-component] like either:
For example, you might be using [can-component] like either:
```js
var can = require("can");
Expand All @@ -197,21 +188,21 @@ var Component = require("can/component/component");
Component.extend({ ... });
```
Which you are using, update your code to instead look like:
Regardless of which you are using, update your code to instead look like:
```js
var Component = require("can-component");

Component.extend({ ... });
```
Use the same pattern for the other can modules you are using. In general you should not be using the `can.` properties any more, but rather importing (through your module loader / bundler) only the packages and modules that you are using.
Use the same pattern for the other `can` modules you are using. In general, you should not be using the `can.` properties any more, but rather importing (through your module loader / bundler) only the packages and modules that you are using.
### Wrap elements in jQuery objects
If you are using [can-jquery/legacy] to get automatically jQuery-wrapped elements in [can-control] event handlers, you’ll want to remove the usage of [can-jquery/legacy] as it doesn’t play well with [can-component]s that do not expect elements to be jQuery-wrapped.
If you are using [can-jquery/legacy] to automatically get jQuery-wrapped elements in [can-control] event handlers, you’ll want to remove the usage of [can-jquery/legacy] as it doesn’t play well with [can-component]s that do not expect elements to be jQuery-wrapped.
Instead use [can-jquery] directly and handle the wrapping yourself. For example:
Instead, use [can-jquery] directly and handle the wrapping yourself. For example:
```js
var Component = require("can-component");
Expand All @@ -233,9 +224,11 @@ Component.extend({
[can-jquery] will continue to be supported indefinitely but [can-jquery/legacy] will be dropped in a future major version.
### Remove use of "change" events
### Remove use of `change` events
When you upgrade to use [can-define], you’ll no longer receive `change` events on maps. If you had any code that binded to a map’s `change` event, you’ll want to instead bind to the properties that you are interested in.
When you upgrade to use [can-define] you’ll no longer receive "change" events on maps. If you had any code that binded on a map's "change" event, you’ll want to instead bind to the properties that you are interested in. For example:
For example:
```js
route.bind("change", function(){
Expand All @@ -255,15 +248,15 @@ routeMap.bind("change", function(){
});
```
As you might notice, we are also favoring using [can-event.on on()] rather than `bind()` now (although bind() still work the same).
As you might notice, [can-event.on on()] is preferable to `bind()`, although `bind()` still works the same.
## Future-proof migration path
In addition to the steps taken in the two above section, if you *really* want to stay ahead of the curve, make the following changes to your application:
In addition to the steps taken in the two sections above, make the following changes to your application if you *really* want to stay ahead of the curve.
### can-define replaces can-map
If you’ve used [can-map-define] in the past then using [can-define] should be familiar to you. Using [can-define/map/map] is the easiest migration path and is what we show in all of the examples in CanJS 3.0’s docs.
If you’ve used [can-map-define] in the past, then using [can-define] should be familiar to you. Using [can-define/map/map] is the easiest migration path and is what we show in all of the examples in CanJS 3’s docs.
A typical map looks like:
Expand Down Expand Up @@ -305,20 +298,20 @@ var CarOwner = DefineMap.extend({
});
```
Using [can-define] allows you to use maps without the [can-map.prototype.attr .attr()] method that’s needed in [can-map] and [can-list]. To use this with DefineMap just use the dot operator instead:
Using [can-define] allows you to use maps without the [can-map.prototype.attr .attr()] method that’s needed in [can-map] and [can-list]. To use this with `DefineMap`, just use the `.` (dot) operator instead:
```js
var carOwner = new CarOwner();

// This is observable!
carOwner.favorite = new Car({ type: "Toyota" });
carOwner.favorite = new Car({ make: "Toyota" });
```
### Use can-connect directly
When using the easy migration path you were secretly using [can-connect/can/model/model], a constructor that is mostly backwards-compatible with [can-model].
When using the easy migration path, you were secretly using [can-connect/can/model/model], a constructor that is mostly backwards-compatible with [can-model](//v2.canjs.com/docs/can.Model.html).
Most new projects should use can-connect directly, and [can-connect/can/super-map/super-map] is the easiest way to create models with connect’s features. Using can-connect directly allows you to use [can-define/map/map]s as your models like so:
Most new projects should use [can-connect] directly. [can-connect/can/super-map/super-map] is the easiest way to create models with `can-connect`’s features. Using `can-connect` directly allows you to use [can-define/map/map]s as your models like so:
```js
var DefineMap = require("can-define/map/map");
Expand All @@ -342,11 +335,11 @@ var messageConnection = superMap({
});
```
### Update use of binding syntax
### Use the new binding syntax
In 2.3 we introduced new binding syntaxes. In 3.0 there are available with [can-stache-bindings]. Although the old binding syntaxes still work, they will likely be dropped in 4.0. View can-stache-binding's documentation to learn how to use the new bindings.
CanJS 2.3 introduced new binding syntaxes. They’re available in CanJS 3 with [can-stache-bindings]. Although the old binding syntaxes still work, they will likely be dropped in 4.0. View [can-stache-bindings]’s documentation to learn how to use the new binding syntax.
An example is changing a can-value binding from:
An example is changing a `can-value` binding from:
```
<input type="text" can-value="{someProp}" />
Expand All @@ -358,9 +351,9 @@ To:
<input type="text" {($value})="someProp" />
```
3.0 also introduces new [can-stache.registerConverter stache converters] which are a special type of [can-stache.Helpers helper] that works two-way to update an element when an observable value changes, and also update the observable value when the form element’s value changes (from user input).
CanJS 3 also introduces new [can-stache.registerConverter stache converters], which are special two-way [can-stache.Helpers helpers] that update an element when an observable value changes and update the observable value when the form element’s value changes (from user input).
An example is the [can-stache-bindings.converters.string-to-any] converter which converts a primitive value to a string to set a `<select>`’s value, and then converts the `<select>` value when a user selects an `<option>` back to the primitive value to update the scope value:
An example is the [can-stache-converters.string-to-any] converter, which converts a primitive value to a string to set a `<select>`’s value, and then converts the `<select>` value when a user selects an `<option>` back to the primitive value to update the scope value:
```
<select {($value)}="string-to-any(~favePlayer)">
Expand Down
2 changes: 1 addition & 1 deletion docs/can-guides/introduction/mission.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ Over the past 9 years of CanJS, the web has evolved, and the best practices in J
To name a few:
- Event delegation became a best practice for managing events around 2009. CanJS added support for event delegation in 2008, before jQuery landed support. Later, when jQuery became ubiquitous, we
integrated jQuery into CanJS.
- RESTful APIs eventually became the best practice for designing a backend interface. [can-model] in 2010 provided ActiveRecord style abstractions around this pattern.
- RESTful APIs eventually became the best practice for designing a backend interface. [can-model](//v2.canjs.com/docs/can.Model.html) in 2010 provided ActiveRecord style abstractions around this pattern.
- Data bindings hit the mainstream in 2013 when Angular rose in popularity. CanJS landed support for this feature in 2011 with [can-ejs].
- Building UI widgets as HTML custom elements, similar to web components, has become a best practice. [can-component] landed in 2013 to support this architecture.
- In 2015, CanJS landed support for using a Virtual DOM and simple server-side rendering with [can-vdom].
Expand Down

0 comments on commit bb2dc7a

Please sign in to comment.