Skip to content

Instantly share code, notes, and snippets.

@leikind
Forked from chrismccord/upgrade.md
Last active March 14, 2017 09:13
Show Gist options
  • Select an option

  • Save leikind/2687ff1cf488b51e424f5e54903c4415 to your computer and use it in GitHub Desktop.

Select an option

Save leikind/2687ff1cf488b51e424f5e54903c4415 to your computer and use it in GitHub Desktop.
Phoenix 1.2.x to 1.3.0 Upgrade Instructions

If you want a run-down of the 1.3 changes and the design decisions behidn those changes, check out the LonestarElixir Phoenix 1.3 keynote: https://www.youtube.com/watch?v=tMO28ar0lW8

To use the new phx.new project generator, you can install the archive with the following command:

$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez

Bump your phoenix dep

Phoenix v1.3.0 is a backwards compatible release with v1.2.x. To upgrade your existing 1.2.x project, simply bump your phoenix dependency in mix.exs:

def deps do
  [{:phoenix, "~> 1.3.0-rc"},
   ...]
end

Update your project the new 1.3 directory structure (optional)

mix.exs

In mix.exs, update your elixirc_paths/1 clauses to remove "web":

- defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
- defp elixirc_paths(_),     do: ["lib", "web"]
+ defp elixirc_paths(:test), do: ["lib", "test/support"]
+ defp elixirc_paths(_),     do: ["lib"]

If you have a reloadable_paths configuration in your config/dev.exs, you may remove this value as all elixirc_paths are now reloaded in dev by default.

Move your root-level web/ directory to lib/app_name/web, and migrate to new Web namespace

The root level web/ directory for new projects has been removed in favor of lib/my_app/web. Additionally, a Web namespace convention has been added to isolate the web interface from your elixir application.

Migrate your files to the new structure with the following steps:

  1. $ cd my_app
  2. $ mv web lib/my_app/web
  3. Update your view root path in web.ex to point to the new template location, and add the :namespace option:
  def view do
    quote do
-      use Phoenix.View, root: "web/templates"
+      use Phoenix.View, root: "lib/my_app/web/templates",
+                        namespace: MyApp.Web
       ...
  1. Add the namespace option to your controller definition in web.ex:
  def controller do
    quote do
-     use Phoenix.Controller
+     use Phoenix.Controller, namespace: MyApp.Web
  1. Update your aliases in web.ex controller, view, and channel definitions to use the new Web namespace:
  def controller do
    quote do
      ...
-     import MyApp.Router.Helpers
+     import MyApp.Web.Router.Helpers
-     import MyApp.Gettext
+     import MyApp.Web.Gettext
    end
  end

  def view do
    quote do
      ...
-     import MyApp.Router.Helpers
+     import MyApp.Web.Router.Helpers
-     import MyApp.ErrorHelpers
+     import MyApp.WebErrorHelpers
-     import MyApp.Gettext
+     import MyApp.Web.Gettext
    end
  end

  def channel do
    quote do
      ...
-     import MyApp.Gettext
+     import MyApp.Web.Gettext
    end
  end
  1. Rename all web related modules in lib/my_app/web/ (gettext.ex, controllers/*, views/*, channels/*, endpoint.ex, router.ex) to include a Web namespace, for example:
  • MyApp.Endpoint => MyApp.Web.Endpoint
  • MyApp.Router => MyApp.Web.Router
  • MyApp.PageController => MyApp.Web.PageController
  • MyApp.PageView => MyApp.Web.PageView
  • MyApp.UserSocket => MyApp.Web.UserSocket
  • etc
  1. Update all alias in lib/app_name/web/router.ex to include new Web namespace. Most likely you can accomplish this by adding .Web to the second argument of your scope blocks, for example:
- defmodule MyApp.Router do
+ defmodule MyApp.Web.Router do
  ...
-   scope "/", MyApp do
+   scope "/", MyApp.Web do
      pipe_through :browser
     
      resources "/users", UserController
      ...
   end
  1. Update endpoint.ex to use new web modules:
- defmodule MyApp.Endpoint do
+ defmodule MyApp.Web.Endpoint do
    ...
-   socket "/socket", MyApp.UserSocket
+   socket "/socket", MyApp.Web.UserSocket
    ...
-   plug MyApp.Router
+   plug MyApp.Web.Router
  1. in lib/my_app.ex, update your children to reference the new endpoint and remove the config_change callback:
    ...
    children = [
      ...
-     supervisor(MyApp.Endpoint, []),
+     supervisor(MyApp.Web.Endpoint, []),
      ...
    ]
    
  ...
- def config_change(changed, _new, removed) do
-   MyApp.Endpoint.config_change(changed, removed)
-   :ok
- end
  1. Update all endpoint aliases in config/*.exs (config.exs, prod.exs, prod.secret.exs dev.exs, test.exs, etc) aliases to use new Web namespace:
- config :my_app, MyApp.Endpoint,
+ config :my_app, MyApp.Web.Endpoint,
    ...
-   render_errors: [view: MyApp.ErrorView, accepts: ~w(html json)],
+   render_errors: [view: MyApp.Web.ErrorView, accepts: ~w(html json)],
  ...
  1. Update your live-reload patterns config in config/dev.exs:
- config :my_app, MyApp.Endpoint,
+ config :my_app, MyApp.Web.Endpoint,
    live_reload: [
      patterns: [
        ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
        ~r{priv/gettext/.*(po)$},
-       ~r{web/views/.*(ex)$},
-       ~r{web/templates/.*(eex)$}
+       ~r{lib/my_app/web/views/.*(ex)$},
+       ~r{lib/my_app/web/templates/.*(eex)$}
      ]
    ]
  1. Rename your test/support/conn_case.ex and test/support/channel_case.ex modules to include Web namespace, and update @endpoint and router aliases in each:
-defmodule MyApp.ConnCase do
+defmodule MyApp.Web.ConnCase do
  using do
    quote do
      ...
-     import MyApp.Router.Helpers
+     import MyApp.Web.Router.Helpers

      # The default endpoint for testing
-     @endpoint MyApp.Endpoint
+     @endpoint MyApp.Web.Endpoint
    end
  end
  ...


-defmodule MyApp.ChannelCase do
+defmodule MyApp.Web.ChannelCase do

  using do
    quote do
      ...
-     @endpoint MyApp.Endpoint
+     @endpoint MyApp.Web.Endpoint
    end
  end
  ...
  1. Update all test/*/**.exs references to use MyApp.ConnCase or use MyApp.ChannelCase to use new MyApp.Web.ConnCase and MyApp.Web.ChannelCase aliases.

Move static assets inside self-contained assets/ directory

New projects now include a root-level assets/ directory, which serves as a self-contained location for your asset builder's config, source files, and packages. This changer keeps things like node_modules, package.json, and brunch-config.js from leaking into the root of your elixir application. Update your app to the new structure by following these steps:

  1. move all web/static/ sources into assets/, followed by package.json, node_modules, and brunch-config.js
$ mv mv lib/my_app/web/static assets/
$ mv assets/assets assets/static
$ mv package.json assets/
$ mv brunch-config.js assets/
$ rm -rf node_modules
  1. Update your asset/package.json phoenix and phoenix_html paths:
  "dependencies": {
-   "phoenix": "file:deps/phoenix",
+   "phoenix": "file:../deps/phoenix",
-   "phoenix_html": "file:deps/phoenix_html"
+   "phoenix_html": "file:../deps/phoenix_html"
  },
  1. Update your assets/brunch-config.js to be aware of the new conventions:
  conventions: {
-   // This option sets where we should place non-css and non-js assets in.
-   // By default, we set this to "/web/static/assets". Files in this directory
-   // will be copied to `paths.public`, which is "priv/static" by default.
-   assets: /^(web\/static\/assets)/
+   // This option sets where we should place non-css and non-js assets in.
+   // By default, we set this to "/assets/static". Files in this directory
+   // will be copied to `paths.public`, which is "priv/static" by default.
+   assets: /^(static)/
  },
  
  paths: {
    // Dependencies and current project directories to watch
-   watched: [
-     "web/static",
-     "test/static"
-   ],
+   watched: ["static", "css", "js", "vendor"],

    // Where to compile files to
-   public: "priv/static"
+   public: "../priv/static"
  },

  plugins: {
    babel: {
      // Do not use ES6 compiler in vendor code
-     ignore: [/web\/static\/vendor/]
+     ignore: [/vendor/]
    }
  },

  modules: {
    autoRequire: {
-     "js/app.js": ["web/static/js/app"]
+     "js/app.js": ["js/app"]
    }
  },
  1. Update your config/dev.exs watcher to run in the new assets directory:
config :my_app, MyApp.Web.Endpoint,
  ...
  watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
-                  cd: Path.expand("../", __DIR__)]]
+                  cd: Path.expand("../assets", __DIR__)]]

  1. Install the node deps: $cd assets && npm install

Test it all with mix phx.server, and mix test and you should see:

$ mix phx.server
[info] Running MyApp.Web.Endpoint with Cowboy using http://0.0.0.0:4000
01 Mar 15:40:05 - info: compiled 6 files into 2 files, copied 3 in 976ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment