
# Upgrading to 0.17

Upgrading should be pretty easy. Everything is quite mechanical, so I would not be very afraid of this process.


## Update elm-package.json

Some core packages have been renamed:

  - `evancz/elm-html` is now `elm-lang/html`
  - `evancz/elm-svg` is now `elm-lang/svg`
  - `evancz/virtual-dom` is now `elm-lang/virtual-dom`
  - The functionality of `evancz/start-app` now lives in `elm-lang/html` in `Html.App`
  - The functionality of `evancz/elm-effects` now lives in `elm-lang/core` in `Platform.*`
  - The functionality of `Graphics.*` now lives in `evancz/elm-graphics`

So the first thing you want to do is update your `elm-package.json` file. Here is one that has been properly updated:

```json
{
    "version": "1.0.0",
    "summary": "let people do a cool thing in a fun way",
    "repository": "https://github.com/user/project.git",
    "license": "BSD3",
    "source-directories": [
        "src"
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "4.0.0 <= v < 5.0.0",
        "elm-lang/html": "1.0.0 <= v < 2.0.0",
        "evancz/elm-http": "3.0.1 <= v < 4.0.0",
        "evancz/elm-markdown": "3.0.0 <= v < 4.0.0"
    },
    "elm-version": "0.17.0 <= v < 0.18.0"
}
```

The only changes should be in the `dependencies` and `elm-version` fields where you need to update constraints. The easiest way to get this all set up is to update `elm-version` by hand, and then remove everything from `dependencies` so you can install the dependencies you still need one at a time with `elm package install`.

## Updating Syntax

The major syntax changes are:

     feature
     0.16
     0.17

     module declaration
     
module Queue (..) where

module Queue exposing (..)

This is a super easy change, so we will add a link to an auto-upgrade tool here when one exists.

## `Action` is now `Msg`

The Elm Architecture tutorial uses the term `Action` for the data that gets fed into your `update` function. This is a silly name. So in 0.17 the standard name is *message*.

```elm
-- 0.16
type Action = Increment | Decrement

-- 0.17
type Msg = Increment | Decrement
```

The idea is that your app is receiving *messages* from the user, from servers, from the browser, etc. Your app then reacts to these messages in the `update` function.


## No More `Signal.Address`

The most common thing in your code will probably be that `Signal.Address` no longer exists. Here is a before and after of upgrading some typical `view` code.

```elm
-- 0.16
view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ button [ onClick address Decrement ] [ text "-" ]
    , div [ countStyle ] [ text (toString model) ]
    , button [ onClick address Increment ] [ text "+" ]
    ]

-- 0.17
view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [ countStyle ] [ text (toString model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]
```

This change is pretty simple. Any occurance of `address` just gets deleted. In the types, you see the addresses removed, and `Html` becomes `Html Msg`. You can read `Html Msg` as "an HTML node that can produce messages of type `Msg`". This change makes addresses unnecessary and makes it much clearer what kind of messages can be produced by a particular block of HTML.

The `Signal.forwardTo` function is replaced by `Html.App.map`. So you may need to make changes like this:

```elm
-- 0.16
view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ Counter.view (Signal.forwardTo address Top) model.topCounter
    , Counter.view (Signal.forwardTo address Bottom) model.bottomCounter
    , button [ onClick address Reset ] [ text "RESET" ]
    ]

-- 0.17
view : Model -> Html Msg
view model =
  div []
    [ map Top (Counter.view model.topCounter)
    , map Bottom (Counter.view model.bottomCounter)
    , button [ onClick Reset ] [ text "RESET" ]
    ]
```

These changes are nice for a couple really good reasons:

  - Addresses were consistently one of the things that new folks found most confusing.
  - It allows the `elm-lang/virtual-dom` implementation to be more efficient with `lazy`
  - It uses a normal `map` instead of some unfamiliar API.

You can see more examples of the new HTML API [here](https://evancz.gitbooks.io/an-introduction-to-elm/content/architecture/user_input/index.html).


## `Effects` is now `Cmd`

If you are working with HTTP or anything, you are probably using `evancz/elm-effects` and have your `update` function returning `Effects` values. That library was a successful experiment, so it has been folded into `elm-lang/core` and given a name that works better in the context of Elm 0.17.

The changes are basically a simple rename:

```elm
-- 0.16
update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    RequestMore ->
      (model, getRandomGif model.topic)

    NewGif maybeUrl ->
      ( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl)
      , Effects.none
      )

-- 0.17
update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    RequestMore ->
      ( model, getRandomGif model.topic )

    NewGif maybeUrl ->
      ( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl)
      , Cmd.none
      )
```

The `Cmd` stuff lives in `elm-lang/core` in `Platform.Cmd`. It is imported by default with `import Platform.Cmd as Cmd exposing (Cmd)` to make it easier to use.

Again, very easy changes. The key goal of 0.17 was to manage effects in a nicer way, so in making these facilities more complete, the term `Effects` became very ambiguous. You should read more about this in the updated Elm Architecture Tutorial which has [a section all about effects](https://evancz.gitbooks.io/an-introduction-to-elm/content/architecture/effects/index.html).


## `StartApp` is now `Html.App`

The `evancz/start-app` package was an experiment to help people get productive with Elm more quickly. It meant that newcomers could get really far with Elm without knowing a ton about signals, and it has been very effective. With 0.17, it has been folded in to `elm-lang/html` in the `Html.App` module.

Upgrading looks like this:

```elm
-- 0.16 ---------------------------------------
import StartApp
import Task

app =
  StartApp.start
    { init = init, update = update, view = view, inputs = [] }

main =
  app.html

port tasks : Signal (Task.Task Never ())
port tasks =
  app.tasks

-- 0.17 ---------------------------------------
import Html.App as Html

main =
  Html.program
    { init = init, update = update, view = view, subscriptions = \_ -> Sub.none }
```

The type of `main` has changed from `Signal Html` to `Program flags`. The main value is a program that knows exactly how it needs to be set up. All that will be handled by Elm, so you no longer need to specially hook tasks up to a port or anything.


## Upgrading Ports

Talking to JavaScript still uses ports. It is pretty similar, but adapted to fit nicely with commands and subscriptions.

Here is the change for *outgoing* ports:

```elm
-- 0.16
port focus : Signal String
port focus =
  ...

-- 0.17
port focus : String -> Cmd msg
```

Instead of hooking up a signal, you have a function that can create commands. So you just call `focus : String -> Cmd msg` from anywhere in your app and the command is processed like all the others.

And here is the change for *incoming* ports:

```elm
type User = { name : String, age : Int }

-- 0.16
port users : Signal User

-- 0.17
port users : (User -> msg) -> Sub msg
```

Instead of getting a signal to route to the right place, we now can create subscriptions to incoming ports. So wherever you need to know about users, you just subscribe to it.

You should definitely read more about this [here](https://evancz.gitbooks.io/an-introduction-to-elm/content/interop/javascript.html).

## JavaScript Interop

The style of initializing Elm programs in JS has also changed slightly.

     Initialize
     0.16
     0.17

     Embed
     
Elm.embed(Elm.Main, someNode);

Elm.Main.embed(someNode);

     Fullscreen
     
Elm.fullscreen(Elm.Main);

Elm.Main.fullscreen();

     Worker
     
Elm.worker(Elm.Main);

Elm.Main.worker();

## Next Steps

From here, I would highly recommend looking through [guide.elm-lang.org](http://guide.elm-lang.org/), particularly the sections on [The Elm Architecture](http://guide.elm-lang.org/architecture/index.html). This will help you get a feel for 0.17.
