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`: ```elixir def deps do [{:phoenix, "~> 1.3.0-rc"}, ...] end ``` ## Update your static manifest location If using the digest task (mix phoenix.digest), the location of the built manifest has changed from `priv/static/manifest.json` to `priv/static/cache_manifest.json`. Update your `config/prod.exs` endpoint config with the following changes: ```diff -cache_static_manifest: "priv/static/cache_manifest.json" +cache_static_manifest: "priv/static/cache_manifest.json" ``` Next, run `mix deps.get` and you're all set! Continue reading to jump on the latest project structure conventions (optional). ## Update your project the new 1.3 directory structure (optional) ### mix.exs In `mix.exs`, update your `elixirc_paths/1` clauses to remove "web": ```diff - 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. `$ mv lib/my_app/endpoint.ex lib/my_app/web/` 4. Update your view root path in `web.ex` to point to the new template location, and add the `:namespace` option: ```diff def view do quote do - use Phoenix.View, root: "web/templates" + use Phoenix.View, root: "lib/my_app/web/templates", + namespace: MyApp.Web ... ``` 4. Add the namespace option to your `controller` definition in `web.ex`: ```diff def controller do quote do - use Phoenix.Controller + use Phoenix.Controller, namespace: MyApp.Web ``` 5. Update your aliases in web.ex `controller`, `view`, and `channel` definitions to use the new `Web` namespace: ```diff 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 ``` 6. 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 7. 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: ```diff - defmodule MyApp.Router do + defmodule MyApp.Web.Router do ... - scope "/", MyApp do + scope "/", MyApp.Web do pipe_through :browser resources "/users", UserController ... end ``` 8. Update `endpoint.ex` to use new web modules: ```diff - 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 ``` 8. in `lib/my_app.ex`, update your children to reference the new endpoint and remove the config_change callback: ```diff ... children = [ ... - supervisor(MyApp.Endpoint, []), + supervisor(MyApp.Web.Endpoint, []), ... ] ... - def config_change(changed, _new, removed) do - MyApp.Endpoint.config_change(changed, removed) - :ok - end ``` 8. 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: ```diff - 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)], ... ``` 9. Update your live-reload patterns config in `config/dev.exs`: ```diff - 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)$} ] ] ``` 10. 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: ```diff -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 ... ``` 11. 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` ```console $ 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 ``` 2) Update your `asset/package.json` `phoenix` and `phoenix_html` paths: ```diff "dependencies": { - "phoenix": "file:deps/phoenix", + "phoenix": "file:../deps/phoenix", - "phoenix_html": "file:deps/phoenix_html" + "phoenix_html": "file:../deps/phoenix_html" }, ``` 3) Update your `assets/brunch-config.js` to be aware of the new conventions: ```diff 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"] } }, ``` 4) Update your `config/dev.exs` watcher to run in the new assets directory: ```diff config :my_app, MyApp.Web.Endpoint, ... watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin", - cd: Path.expand("../", __DIR__)]] + cd: Path.expand("../assets", __DIR__)]] ``` 5. 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 ```